Initial commit

This commit is contained in:
Brian Harris
2012-11-26 12:58:24 -06:00
parent a5214f79ef
commit 5016f605b8
1115 changed files with 587266 additions and 0 deletions

21
neo/_Common.props Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<_PropertySheetDisplayName>Common Project Properties</_PropertySheetDisplayName>
<OutDir>..\build\$(PlatformName)\$(Configuration)\</OutDir>
<IntDir>..\build\$(PlatformName)\$(Configuration)\intermediate\$(ProjectName)\</IntDir>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<ImageXexOutput>$(OutDir)$(ProjectName).xex</ImageXexOutput>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level4</WarningLevel>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>$(SolutionDir)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
</Project>

23
neo/_Debug.props Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<_PropertySheetDisplayName>Debug</_PropertySheetDisplayName>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<SmallerTypeCheck>false</SmallerTypeCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
</Link>
</ItemDefinitionGroup>
</Project>

12
neo/_Dedicated.props Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<_PropertySheetDisplayName>Dedicated</_PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>ID_DEDICATED;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</Project>

18
neo/_DoomExe.props Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<_PropertySheetDisplayName>Doom III Executable</_PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>__DOOM__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<StackReserveSize>16777216</StackReserveSize>
<StackCommitSize>16777216</StackCommitSize>
<LargeAddressAware>true</LargeAddressAware>
</Link>
</ItemDefinitionGroup>
</Project>

21
neo/_Game-d3xp.props Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<_PropertySheetDisplayName>Game d3xp Library</_PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>__DOOM__;_D3XP;CTF;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<OutputFile Condition="'$(Platform)'=='Win32'">$(OutDir)gamex86.dll</OutputFile>
<ModuleDefinitionFile>.\d3xp\game.def</ModuleDefinitionFile>
</Link>
<PreBuildEvent>
<Command>..\build\Win32\"$(Configuration)"\TypeInfo.exe</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
</Project>

22
neo/_Game.props Normal file
View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<_PropertySheetDisplayName>Game Library</_PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>__DOOM__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<OutputFile Condition="'$(Platform)'=='Win32'">$(OutDir)gamex86.dll</OutputFile>
<ModuleDefinitionFile>.\game\game.def</ModuleDefinitionFile>
</Link>
<PreBuildEvent>
<Command>..\build\Win32\"$(Configuration)"\TypeInfo.exe</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
</Project>

25
neo/_PCLibs.props Normal file
View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<_PropertySheetDisplayName>PC Libs</_PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<Link Condition="'$(Configuration)'=='Debug'">
<AdditionalDependencies>libcmtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libcmtd.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
</Link>
<Link Condition="'$(Configuration)'!='Debug'">
<AdditionalDependencies>libcmt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libcmt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
</Link>
<Link>
<AdditionalDependencies>xinput.lib;dbghelp.lib;dinput8.lib;dsound.lib;dxguid.lib;DxErr.lib;glu32.lib;iphlpapi.lib;odbc32.lib;odbccp32.lib;opengl32.lib;winmm.lib;wsock32.lib;x3daudio.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(DXSDK_DIR)\Lib\x86\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Windows</SubSystem>
</Link>
<ClCompile>
<AdditionalIncludeDirectories>$(DXSDK_DIR)\Include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
</Project>

27
neo/_Release.props Normal file
View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<_PropertySheetDisplayName>Release</_PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateMapFile>false</GenerateMapFile>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
</ItemDefinitionGroup>
</Project>

13
neo/_WithInlines.props Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<_PropertySheetDisplayName>With Inlines</_PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<PreprocessorDefinitions>_INLINEDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</Project>

12
neo/_WithMemoryLog.props Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<_PropertySheetDisplayName>With Memory Log</_PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>ID_REDIRECT_NEWDELETE;ID_DEBUG_MEMORY;ID_DEBUG_UNINITIALIZED_MEMORY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</Project>

14
neo/_external.props Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_PropertySheetDisplayName>External</_PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)renderer\jpeg-6;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

13
neo/_idlib.props Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<_PropertySheetDisplayName>idlib</_PropertySheetDisplayName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>__IDLIB__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
</ItemDefinitionGroup>
</Project>

1317
neo/aas/AASFile.cpp Normal file

File diff suppressed because it is too large Load Diff

351
neo/aas/AASFile.h Normal file
View File

@@ -0,0 +1,351 @@
/*
===========================================================================
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 __AASFILE_H__
#define __AASFILE_H__
/*
===============================================================================
AAS File
===============================================================================
*/
#define AAS_FILEID "DewmAAS"
#define AAS_FILEVERSION "1.07"
// travel flags
#define TFL_INVALID BIT(0) // not valid
#define TFL_WALK BIT(1) // walking
#define TFL_CROUCH BIT(2) // crouching
#define TFL_WALKOFFLEDGE BIT(3) // walking of a ledge
#define TFL_BARRIERJUMP BIT(4) // jumping onto a barrier
#define TFL_JUMP BIT(5) // jumping
#define TFL_LADDER BIT(6) // climbing a ladder
#define TFL_SWIM BIT(7) // swimming
#define TFL_WATERJUMP BIT(8) // jump out of the water
#define TFL_TELEPORT BIT(9) // teleportation
#define TFL_ELEVATOR BIT(10) // travel by elevator
#define TFL_FLY BIT(11) // fly
#define TFL_SPECIAL BIT(12) // special
#define TFL_WATER BIT(21) // travel through water
#define TFL_AIR BIT(22) // travel through air
// face flags
#define FACE_SOLID BIT(0) // solid at the other side
#define FACE_LADDER BIT(1) // ladder surface
#define FACE_FLOOR BIT(2) // standing on floor when on this face
#define FACE_LIQUID BIT(3) // face seperating two areas with liquid
#define FACE_LIQUIDSURFACE BIT(4) // face seperating liquid and air
// area flags
#define AREA_FLOOR BIT(0) // AI can stand on the floor in this area
#define AREA_GAP BIT(1) // area has a gap
#define AREA_LEDGE BIT(2) // if entered the AI bbox partly floats above a ledge
#define AREA_LADDER BIT(3) // area contains one or more ladder faces
#define AREA_LIQUID BIT(4) // area contains a liquid
#define AREA_CROUCH BIT(5) // AI cannot walk but can only crouch in this area
#define AREA_REACHABLE_WALK BIT(6) // area is reachable by walking or swimming
#define AREA_REACHABLE_FLY BIT(7) // area is reachable by flying
// area contents flags
#define AREACONTENTS_SOLID BIT(0) // solid, not a valid area
#define AREACONTENTS_WATER BIT(1) // area contains water
#define AREACONTENTS_CLUSTERPORTAL BIT(2) // area is a cluster portal
#define AREACONTENTS_OBSTACLE BIT(3) // area contains (part of) a dynamic obstacle
#define AREACONTENTS_TELEPORTER BIT(4) // area contains (part of) a teleporter trigger
// bits for different bboxes
#define AREACONTENTS_BBOX_BIT 24
#define MAX_REACH_PER_AREA 256
#define MAX_AAS_TREE_DEPTH 128
#define MAX_AAS_BOUNDING_BOXES 4
// reachability to another area
class idReachability {
public:
int travelType; // type of travel required to get to the area
short toAreaNum; // number of the reachable area
short fromAreaNum; // number of area the reachability starts
idVec3 start; // start point of inter area movement
idVec3 end; // end point of inter area movement
int edgeNum; // edge crossed by this reachability
unsigned short travelTime; // travel time of the inter area movement
byte number; // reachability number within the fromAreaNum (must be < 256)
byte disableCount; // number of times this reachability has been disabled
idReachability * next; // next reachability in list
idReachability * rev_next; // next reachability in reversed list
unsigned short * areaTravelTimes; // travel times within the fromAreaNum from reachabilities that lead towards this area
public:
void CopyBase( idReachability &reach );
};
class idReachability_Walk : public idReachability {
};
class idReachability_BarrierJump : public idReachability {
};
class idReachability_WaterJump : public idReachability {
};
class idReachability_WalkOffLedge : public idReachability {
};
class idReachability_Swim : public idReachability {
};
class idReachability_Fly : public idReachability {
};
class idReachability_Special : public idReachability {
public:
idDict dict;
};
// index
typedef int aasIndex_t;
// vertex
typedef idVec3 aasVertex_t;
// edge
typedef struct aasEdge_s {
int vertexNum[2]; // numbers of the vertexes of this edge
} aasEdge_t;
// area boundary face
typedef struct aasFace_s {
unsigned short planeNum; // number of the plane this face is on
unsigned short flags; // face flags
int numEdges; // number of edges in the boundary of the face
int firstEdge; // first edge in the edge index
short areas[2]; // area at the front and back of this face
} aasFace_t;
// area with a boundary of faces
typedef struct aasArea_s {
int numFaces; // number of faces used for the boundary of the area
int firstFace; // first face in the face index used for the boundary of the area
idBounds bounds; // bounds of the area
idVec3 center; // center of the area an AI can move towards
unsigned short flags; // several area flags
unsigned short contents; // contents of the area
short cluster; // cluster the area belongs to, if negative it's a portal
short clusterAreaNum; // number of the area in the cluster
int travelFlags; // travel flags for traveling through this area
idReachability * reach; // reachabilities that start from this area
idReachability * rev_reach; // reachabilities that lead to this area
} aasArea_t;
// nodes of the bsp tree
typedef struct aasNode_s {
unsigned short planeNum; // number of the plane that splits the subspace at this node
int children[2]; // child nodes, zero is solid, negative is -(area number)
} aasNode_t;
// cluster portal
typedef struct aasPortal_s {
short areaNum; // number of the area that is the actual portal
short clusters[2]; // number of cluster at the front and back of the portal
short clusterAreaNum[2]; // number of this portal area in the front and back cluster
unsigned short maxAreaTravelTime; // maximum travel time through the portal area
} aasPortal_t;
// cluster
typedef struct aasCluster_s {
int numAreas; // number of areas in the cluster
int numReachableAreas; // number of areas with reachabilities
int numPortals; // number of cluster portals
int firstPortal; // first cluster portal in the index
} aasCluster_t;
// trace through the world
typedef struct aasTrace_s {
// parameters
int flags; // areas with these flags block the trace
int travelFlags; // areas with these travel flags block the trace
int maxAreas; // size of the 'areas' array
int getOutOfSolid; // trace out of solid if the trace starts in solid
// output
float fraction; // fraction of trace completed
idVec3 endpos; // end position of trace
int planeNum; // plane hit
int lastAreaNum; // number of last area the trace went through
int blockingAreaNum; // area that could not be entered
int numAreas; // number of areas the trace went through
int * areas; // array to store areas the trace went through
idVec3 * points; // points where the trace entered each new area
aasTrace_s() { areas = NULL; points = NULL; getOutOfSolid = false; flags = travelFlags = maxAreas = 0; }
} aasTrace_t;
// settings
class idAASSettings {
public:
// collision settings
int numBoundingBoxes;
idBounds boundingBoxes[MAX_AAS_BOUNDING_BOXES];
bool usePatches;
bool writeBrushMap;
bool playerFlood;
bool noOptimize;
bool allowSwimReachabilities;
bool allowFlyReachabilities;
idStr fileExtension;
// physics settings
idVec3 gravity;
idVec3 gravityDir;
idVec3 invGravityDir;
float gravityValue;
float maxStepHeight;
float maxBarrierHeight;
float maxWaterJumpHeight;
float maxFallHeight;
float minFloorCos;
// fixed travel times
int tt_barrierJump;
int tt_startCrouching;
int tt_waterJump;
int tt_startWalkOffLedge;
public:
idAASSettings();
bool FromFile( const idStr &fileName );
bool FromParser( idLexer &src );
bool FromDict( const char *name, const idDict *dict );
bool WriteToFile( idFile *fp ) const;
bool ValidForBounds( const idBounds &bounds ) const;
bool ValidEntity( const char *classname ) const;
private:
bool ParseBool( idLexer &src, bool &b );
bool ParseInt( idLexer &src, int &i );
bool ParseFloat( idLexer &src, float &f );
bool ParseVector( idLexer &src, idVec3 &vec );
bool ParseBBoxes( idLexer &src );
};
/*
- when a node child is a solid leaf the node child number is zero
- two adjacent areas (sharing a plane at opposite sides) share a face
this face is a portal between the areas
- when an area uses a face from the faceindex with a positive index
then the face plane normal points into the area
- the face edges are stored counter clockwise using the edgeindex
- two adjacent convex areas (sharing a face) only share One face
this is a simple result of the areas being convex
- the areas can't have a mixture of ground and gap faces
other mixtures of faces in one area are allowed
- areas with the AREACONTENTS_CLUSTERPORTAL in the settings have
the cluster number set to the negative portal number
- edge zero is a dummy
- face zero is a dummy
- area zero is a dummy
- node zero is a dummy
- portal zero is a dummy
- cluster zero is a dummy
*/
class idAASFile {
public:
virtual ~idAASFile() {}
const char * GetName() const { return name.c_str(); }
unsigned int GetCRC() const { return crc; }
int GetNumPlanes() const { return planeList.Num(); }
const idPlane & GetPlane( int index ) const { return planeList[index]; }
int GetNumVertices() const { return vertices.Num(); }
const aasVertex_t & GetVertex( int index ) const { return vertices[index]; }
int GetNumEdges() const { return edges.Num(); }
const aasEdge_t & GetEdge( int index ) const { return edges[index]; }
int GetNumEdgeIndexes() const { return edgeIndex.Num(); }
const aasIndex_t & GetEdgeIndex( int index ) const { return edgeIndex[index]; }
int GetNumFaces() const { return faces.Num(); }
const aasFace_t & GetFace( int index ) const { return faces[index]; }
int GetNumFaceIndexes() const { return faceIndex.Num(); }
const aasIndex_t & GetFaceIndex( int index ) const { return faceIndex[index]; }
int GetNumAreas() const { return areas.Num(); }
const aasArea_t & GetArea( int index ) { return areas[index]; }
int GetNumNodes() const { return nodes.Num(); }
const aasNode_t & GetNode( int index ) const { return nodes[index]; }
int GetNumPortals() const { return portals.Num(); }
const aasPortal_t & GetPortal( int index ) { return portals[index]; }
int GetNumPortalIndexes() const { return portalIndex.Num(); }
const aasIndex_t & GetPortalIndex( int index ) const { return portalIndex[index]; }
int GetNumClusters() const { return clusters.Num(); }
const aasCluster_t & GetCluster( int index ) const { return clusters[index]; }
const idAASSettings & GetSettings() const { return settings; }
void SetPortalMaxTravelTime( int index, int time ) { portals[index].maxAreaTravelTime = time; }
void SetAreaTravelFlag( int index, int flag ) { areas[index].travelFlags |= flag; }
void RemoveAreaTravelFlag( int index, int flag ) { areas[index].travelFlags &= ~flag; }
virtual idVec3 EdgeCenter( int edgeNum ) const = 0;
virtual idVec3 FaceCenter( int faceNum ) const = 0;
virtual idVec3 AreaCenter( int areaNum ) const = 0;
virtual idBounds EdgeBounds( int edgeNum ) const = 0;
virtual idBounds FaceBounds( int faceNum ) const = 0;
virtual idBounds AreaBounds( int areaNum ) const = 0;
virtual int PointAreaNum( const idVec3 &origin ) const = 0;
virtual int PointReachableAreaNum( const idVec3 &origin, const idBounds &searchBounds, const int areaFlags, const int excludeTravelFlags ) const = 0;
virtual int BoundsReachableAreaNum( const idBounds &bounds, const int areaFlags, const int excludeTravelFlags ) const = 0;
virtual void PushPointIntoAreaNum( int areaNum, idVec3 &point ) const = 0;
virtual bool Trace( aasTrace_t &trace, const idVec3 &start, const idVec3 &end ) const = 0;
virtual void PrintInfo() const = 0;
protected:
idStr name;
unsigned int crc;
idPlaneSet planeList;
idList<aasVertex_t, TAG_AAS> vertices;
idList<aasEdge_t, TAG_AAS> edges;
idList<aasIndex_t, TAG_AAS> edgeIndex;
idList<aasFace_t, TAG_AAS> faces;
idList<aasIndex_t, TAG_AAS> faceIndex;
idList<aasArea_t, TAG_AAS> areas;
idList<aasNode_t, TAG_AAS> nodes;
idList<aasPortal_t, TAG_AAS> portals;
idList<aasIndex_t, TAG_AAS> portalIndex;
idList<aasCluster_t, TAG_AAS> clusters;
idAASSettings settings;
};
#endif /* !__AASFILE_H__ */

View File

@@ -0,0 +1,77 @@
/*
===========================================================================
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.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "AASFile.h"
#include "AASFile_local.h"
/*
===============================================================================
AAS File Manager
===============================================================================
*/
class idAASFileManagerLocal : public idAASFileManager {
public:
virtual ~idAASFileManagerLocal() {}
virtual idAASFile * LoadAAS( const char *fileName, unsigned int mapFileCRC );
virtual void FreeAAS( idAASFile *file );
};
idAASFileManagerLocal AASFileManagerLocal;
idAASFileManager * AASFileManager = &AASFileManagerLocal;
/*
================
idAASFileManagerLocal::LoadAAS
================
*/
idAASFile *idAASFileManagerLocal::LoadAAS( const char *fileName, unsigned int mapFileCRC ) {
idAASFileLocal *file = new (TAG_AAS) idAASFileLocal();
if ( !file->Load( fileName, mapFileCRC ) ) {
delete file;
return NULL;
}
return file;
}
/*
================
idAASFileManagerLocal::FreeAAS
================
*/
void idAASFileManagerLocal::FreeAAS( idAASFile *file ) {
delete file;
}

50
neo/aas/AASFileManager.h Normal file
View File

@@ -0,0 +1,50 @@
/*
===========================================================================
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 __AASFILEMANAGER_H__
#define __AASFILEMANAGER_H__
/*
===============================================================================
AAS File Manager
===============================================================================
*/
class idAASFileManager {
public:
virtual ~idAASFileManager() {}
virtual idAASFile * LoadAAS( const char *fileName, unsigned int mapFileCRC ) = 0;
virtual void FreeAAS( idAASFile *file ) = 0;
};
extern idAASFileManager * AASFileManager;
#endif /* !__AASFILEMANAGER_H__ */

99
neo/aas/AASFile_local.h Normal file
View File

@@ -0,0 +1,99 @@
/*
===========================================================================
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 __AASFILELOCAL_H__
#define __AASFILELOCAL_H__
/*
===============================================================================
AAS File Local
===============================================================================
*/
class idAASFileLocal : public idAASFile {
friend class idAASBuild;
friend class idAASReach;
friend class idAASCluster;
public:
idAASFileLocal();
virtual ~idAASFileLocal();
public:
virtual idVec3 EdgeCenter( int edgeNum ) const;
virtual idVec3 FaceCenter( int faceNum ) const;
virtual idVec3 AreaCenter( int areaNum ) const;
virtual idBounds EdgeBounds( int edgeNum ) const;
virtual idBounds FaceBounds( int faceNum ) const;
virtual idBounds AreaBounds( int areaNum ) const;
virtual int PointAreaNum( const idVec3 &origin ) const;
virtual int PointReachableAreaNum( const idVec3 &origin, const idBounds &searchBounds, const int areaFlags, const int excludeTravelFlags ) const;
virtual int BoundsReachableAreaNum( const idBounds &bounds, const int areaFlags, const int excludeTravelFlags ) const;
virtual void PushPointIntoAreaNum( int areaNum, idVec3 &point ) const;
virtual bool Trace( aasTrace_t &trace, const idVec3 &start, const idVec3 &end ) const;
virtual void PrintInfo() const;
public:
bool Load( const idStr &fileName, unsigned int mapFileCRC );
bool Write( const idStr &fileName, unsigned int mapFileCRC );
int MemorySize() const;
void ReportRoutingEfficiency() const;
void Optimize();
void LinkReversedReachability();
void FinishAreas();
void Clear();
void DeleteReachabilities();
void DeleteClusters();
private:
bool ParseIndex( idLexer &src, idList<aasIndex_t> &indexes );
bool ParsePlanes( idLexer &src );
bool ParseVertices( idLexer &src );
bool ParseEdges( idLexer &src );
bool ParseFaces( idLexer &src );
bool ParseReachabilities( idLexer &src, int areaNum );
bool ParseAreas( idLexer &src );
bool ParseNodes( idLexer &src );
bool ParsePortals( idLexer &src );
bool ParseClusters( idLexer &src );
private:
int BoundsReachableAreaNum_r( int nodeNum, const idBounds &bounds, const int areaFlags, const int excludeTravelFlags ) const;
void MaxTreeDepth_r( int nodeNum, int &depth, int &maxDepth ) const;
int MaxTreeDepth() const;
int AreaContentsTravelFlags( int areaNum ) const;
idVec3 AreaReachableGoal( int areaNum ) const;
int NumReachabilities() const;
};
#endif /* !__AASFILELOCAL_H__ */

View File

@@ -0,0 +1,155 @@
/*
===========================================================================
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.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "AASFile.h"
#include "AASFile_local.h"
//===============================================================
//
// optimize file
//
//===============================================================
/*
================
idAASFileLocal::Optimize
================
*/
void idAASFileLocal::Optimize() {
int i, j, k, faceNum, edgeNum, areaFirstFace, faceFirstEdge;
aasArea_t *area;
aasFace_t *face;
aasEdge_t *edge;
idReachability *reach;
idList<int> vertexRemap;
idList<int> edgeRemap;
idList<int> faceRemap;
idList<aasVertex_t> newVertices;
idList<aasEdge_t> newEdges;
idList<aasIndex_t> newEdgeIndex;
idList<aasFace_t> newFaces;
idList<aasIndex_t> newFaceIndex;
vertexRemap.AssureSize( vertices.Num(), -1 );
edgeRemap.AssureSize( edges.Num(), 0 );
faceRemap.AssureSize( faces.Num(), 0 );
newVertices.Resize( vertices.Num() );
newEdges.Resize( edges.Num() );
newEdges.SetNum( 1 );
newEdgeIndex.Resize( edgeIndex.Num() );
newFaces.Resize( faces.Num() );
newFaces.SetNum( 1 );
newFaceIndex.Resize( faceIndex.Num() );
for ( i = 0; i < areas.Num(); i++ ) {
area = &areas[i];
areaFirstFace = newFaceIndex.Num();
for ( j = 0; j < area->numFaces; j++ ) {
faceNum = faceIndex[area->firstFace + j];
face = &faces[ abs(faceNum) ];
// store face
if ( !faceRemap[ abs(faceNum) ] ) {
faceRemap[ abs(faceNum) ] = newFaces.Num();
newFaces.Append( *face );
// don't store edges for faces we don't care about
if ( !( face->flags & ( FACE_FLOOR|FACE_LADDER ) ) ) {
newFaces[ newFaces.Num()-1 ].firstEdge = 0;
newFaces[ newFaces.Num()-1 ].numEdges = 0;
} else {
// store edges
faceFirstEdge = newEdgeIndex.Num();
for ( k = 0; k < face->numEdges; k++ ) {
edgeNum = edgeIndex[ face->firstEdge + k ];
edge = &edges[ abs(edgeNum) ];
if ( !edgeRemap[ abs(edgeNum) ] ) {
if ( edgeNum < 0 ) {
edgeRemap[ abs(edgeNum) ] = -newEdges.Num();
}
else {
edgeRemap[ abs(edgeNum) ] = newEdges.Num();
}
// remap vertices if not yet remapped
if ( vertexRemap[ edge->vertexNum[0] ] == -1 ) {
vertexRemap[ edge->vertexNum[0] ] = newVertices.Num();
newVertices.Append( vertices[ edge->vertexNum[0] ] );
}
if ( vertexRemap[ edge->vertexNum[1] ] == -1 ) {
vertexRemap[ edge->vertexNum[1] ] = newVertices.Num();
newVertices.Append( vertices[ edge->vertexNum[1] ] );
}
newEdges.Append( *edge );
newEdges[ newEdges.Num()-1 ].vertexNum[0] = vertexRemap[ edge->vertexNum[0] ];
newEdges[ newEdges.Num()-1 ].vertexNum[1] = vertexRemap[ edge->vertexNum[1] ];
}
newEdgeIndex.Append( edgeRemap[ abs(edgeNum) ] );
}
newFaces[ newFaces.Num()-1 ].firstEdge = faceFirstEdge;
newFaces[ newFaces.Num()-1 ].numEdges = newEdgeIndex.Num() - faceFirstEdge;
}
}
if ( faceNum < 0 ) {
newFaceIndex.Append( -faceRemap[ abs(faceNum) ] );
} else {
newFaceIndex.Append( faceRemap[ abs(faceNum) ] );
}
}
area->firstFace = areaFirstFace;
area->numFaces = newFaceIndex.Num() - areaFirstFace;
// remap the reachability edges
for ( reach = area->reach; reach; reach = reach->next ) {
reach->edgeNum = abs( edgeRemap[reach->edgeNum] );
}
}
// store new list
vertices = newVertices;
edges = newEdges;
edgeIndex = newEdgeIndex;
faces = newFaces;
faceIndex = newFaceIndex;
}

609
neo/aas/AASFile_sample.cpp Normal file
View File

@@ -0,0 +1,609 @@
/*
===========================================================================
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.
===========================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "AASFile.h"
#include "AASFile_local.h"
//===============================================================
//
// Environment Sampling
//
//===============================================================
/*
================
idAASFileLocal::EdgeCenter
================
*/
idVec3 idAASFileLocal::EdgeCenter( int edgeNum ) const {
const aasEdge_t *edge;
edge = &edges[edgeNum];
return ( vertices[edge->vertexNum[0]] + vertices[edge->vertexNum[1]] ) * 0.5f;
}
/*
================
idAASFileLocal::FaceCenter
================
*/
idVec3 idAASFileLocal::FaceCenter( int faceNum ) const {
int i, edgeNum;
const aasFace_t *face;
const aasEdge_t *edge;
idVec3 center;
center = vec3_origin;
face = &faces[faceNum];
if ( face->numEdges > 0 ) {
for ( i = 0; i < face->numEdges; i++ ) {
edgeNum = edgeIndex[ face->firstEdge + i ];
edge = &edges[ abs( edgeNum ) ];
center += vertices[ edge->vertexNum[ INT32_SIGNBITSET(edgeNum) ] ];
}
center /= face->numEdges;
}
return center;
}
/*
================
idAASFileLocal::AreaCenter
================
*/
idVec3 idAASFileLocal::AreaCenter( int areaNum ) const {
int i, faceNum;
const aasArea_t *area;
idVec3 center;
center = vec3_origin;
area = &areas[areaNum];
if ( area->numFaces > 0 ) {
for ( i = 0; i < area->numFaces; i++ ) {
faceNum = faceIndex[area->firstFace + i];
center += FaceCenter( abs(faceNum) );
}
center /= area->numFaces;
}
return center;
}
/*
============
idAASFileLocal::AreaReachableGoal
============
*/
idVec3 idAASFileLocal::AreaReachableGoal( int areaNum ) const {
int i, faceNum, numFaces;
const aasArea_t *area;
idVec3 center;
idVec3 start, end;
aasTrace_t trace;
area = &areas[areaNum];
if ( !(area->flags & (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY)) || (area->flags & AREA_LIQUID) ) {
return AreaCenter( areaNum );
}
center = vec3_origin;
numFaces = 0;
for ( i = 0; i < area->numFaces; i++ ) {
faceNum = faceIndex[area->firstFace + i];
if ( !(faces[abs(faceNum)].flags & FACE_FLOOR) ) {
continue;
}
center += FaceCenter( abs(faceNum) );
numFaces++;
}
if ( numFaces > 0 ) {
center /= numFaces;
}
center[2] += 1.0f;
end = center;
end[2] -= 1024;
Trace( trace, center, end );
return trace.endpos;
}
/*
================
idAASFileLocal::EdgeBounds
================
*/
idBounds idAASFileLocal::EdgeBounds( int edgeNum ) const {
const aasEdge_t *edge;
idBounds bounds;
edge = &edges[ abs( edgeNum ) ];
bounds[0] = bounds[1] = vertices[ edge->vertexNum[0] ];
bounds += vertices[ edge->vertexNum[1] ];
return bounds;
}
/*
================
idAASFileLocal::FaceBounds
================
*/
idBounds idAASFileLocal::FaceBounds( int faceNum ) const {
int i, edgeNum;
const aasFace_t *face;
const aasEdge_t *edge;
idBounds bounds;
face = &faces[faceNum];
bounds.Clear();
for ( i = 0; i < face->numEdges; i++ ) {
edgeNum = edgeIndex[ face->firstEdge + i ];
edge = &edges[ abs( edgeNum ) ];
bounds.AddPoint( vertices[ edge->vertexNum[ INT32_SIGNBITSET(edgeNum) ] ] );
}
return bounds;
}
/*
================
idAASFileLocal::AreaBounds
================
*/
idBounds idAASFileLocal::AreaBounds( int areaNum ) const {
int i, faceNum;
const aasArea_t *area;
idBounds bounds;
area = &areas[areaNum];
bounds.Clear();
for ( i = 0; i < area->numFaces; i++ ) {
faceNum = faceIndex[area->firstFace + i];
bounds += FaceBounds( abs(faceNum) );
}
return bounds;
}
/*
============
idAASFileLocal::PointAreaNum
============
*/
int idAASFileLocal::PointAreaNum( const idVec3 &origin ) const {
int nodeNum;
const aasNode_t *node;
nodeNum = 1;
do {
node = &nodes[nodeNum];
if ( planeList[node->planeNum].Side( origin ) == PLANESIDE_BACK ) {
nodeNum = node->children[1];
}
else {
nodeNum = node->children[0];
}
if ( nodeNum < 0 ) {
return -nodeNum;
}
} while( nodeNum );
return 0;
}
/*
============
idAASFileLocal::PointReachableAreaNum
============
*/
int idAASFileLocal::PointReachableAreaNum( const idVec3 &origin, const idBounds &searchBounds, const int areaFlags, const int excludeTravelFlags ) const {
int areaList[32], areaNum, i;
idVec3 start, end, pointList[32];
aasTrace_t trace;
idBounds bounds;
float frac;
start = origin;
trace.areas = areaList;
trace.points = pointList;
trace.maxAreas = sizeof( areaList ) / sizeof( int );
trace.getOutOfSolid = true;
areaNum = PointAreaNum( start );
if ( areaNum ) {
if ( ( areas[areaNum].flags & areaFlags ) && ( ( areas[areaNum].travelFlags & excludeTravelFlags ) == 0 ) ) {
return areaNum;
}
}
else {
// trace up
end = start;
end[2] += 32.0f;
Trace( trace, start, end );
if ( trace.numAreas >= 1 ) {
if ( ( areas[0].flags & areaFlags ) && ( ( areas[0].travelFlags & excludeTravelFlags ) == 0 ) ) {
return areaList[0];
}
start = pointList[0];
start[2] += 1.0f;
}
}
// trace down
end = start;
end[2] -= 32.0f;
Trace( trace, start, end );
if ( trace.lastAreaNum ) {
if ( ( areas[trace.lastAreaNum].flags & areaFlags ) && ( ( areas[trace.lastAreaNum].travelFlags & excludeTravelFlags ) == 0 ) ) {
return trace.lastAreaNum;
}
start = trace.endpos;
}
// expand bounds until an area is found
for ( i = 1; i <= 12; i++ ) {
frac = i * ( 1.0f / 12.0f );
bounds[0] = origin + searchBounds[0] * frac;
bounds[1] = origin + searchBounds[1] * frac;
areaNum = BoundsReachableAreaNum( bounds, areaFlags, excludeTravelFlags );
if ( areaNum && ( areas[areaNum].flags & areaFlags ) && ( ( areas[areaNum].travelFlags & excludeTravelFlags ) == 0 ) ) {
return areaNum;
}
}
return 0;
}
/*
============
idAASFileLocal::BoundsReachableAreaNum_r
============
*/
int idAASFileLocal::BoundsReachableAreaNum_r( int nodeNum, const idBounds &bounds, const int areaFlags, const int excludeTravelFlags ) const {
int res;
const aasNode_t *node;
while( nodeNum ) {
if ( nodeNum < 0 ) {
if ( ( areas[-nodeNum].flags & areaFlags ) && ( ( areas[-nodeNum].travelFlags & excludeTravelFlags ) == 0 ) ) {
return -nodeNum;
}
return 0;
}
node = &nodes[nodeNum];
res = bounds.PlaneSide( planeList[node->planeNum] );
if ( res == PLANESIDE_BACK ) {
nodeNum = node->children[1];
}
else if ( res == PLANESIDE_FRONT ) {
nodeNum = node->children[0];
}
else {
nodeNum = BoundsReachableAreaNum_r( node->children[1], bounds, areaFlags, excludeTravelFlags );
if ( nodeNum ) {
return nodeNum;
}
nodeNum = node->children[0];
}
}
return 0;
}
/*
============
idAASFileLocal::BoundsReachableAreaNum
============
*/
int idAASFileLocal::BoundsReachableAreaNum( const idBounds &bounds, const int areaFlags, const int excludeTravelFlags ) const {
return BoundsReachableAreaNum_r( 1, bounds, areaFlags, excludeTravelFlags );
}
/*
============
idAASFileLocal::PushPointIntoAreaNum
============
*/
void idAASFileLocal::PushPointIntoAreaNum( int areaNum, idVec3 &point ) const {
int i, faceNum;
const aasArea_t *area;
const aasFace_t *face;
area = &areas[areaNum];
// push the point to the right side of all area face planes
for ( i = 0; i < area->numFaces; i++ ) {
faceNum = faceIndex[area->firstFace + i];
face = &faces[abs( faceNum )];
const idPlane &plane = planeList[face->planeNum ^ INT32_SIGNBITSET( faceNum )];
float dist = plane.Distance( point );
// project the point onto the face plane if it is on the wrong side
if ( dist < 0.0f ) {
point -= dist * plane.Normal();
}
}
}
/*
============
idAASFileLocal::Trace
============
*/
#define TRACEPLANE_EPSILON 0.125f
typedef struct aasTraceStack_s
{
idVec3 start;
idVec3 end;
int planeNum;
int nodeNum;
} aasTraceStack_t;
bool idAASFileLocal::Trace( aasTrace_t &trace, const idVec3 &start, const idVec3 &end ) const {
int side, nodeNum, tmpPlaneNum;
double front, back, frac;
idVec3 cur_start, cur_end, cur_mid, v1, v2;
aasTraceStack_t tracestack[MAX_AAS_TREE_DEPTH];
aasTraceStack_t *tstack_p;
const aasNode_t *node;
const idPlane *plane;
trace.numAreas = 0;
trace.lastAreaNum = 0;
trace.blockingAreaNum = 0;
tstack_p = tracestack;
tstack_p->start = start;
tstack_p->end = end;
tstack_p->planeNum = 0;
tstack_p->nodeNum = 1; //start with the root of the tree
tstack_p++;
while( 1 ) {
tstack_p--;
// if the trace stack is empty
if ( tstack_p < tracestack ) {
if ( !trace.lastAreaNum ) {
// completely in solid
trace.fraction = 0.0f;
trace.endpos = start;
}
else {
// nothing was hit
trace.fraction = 1.0f;
trace.endpos = end;
}
trace.planeNum = 0;
return false;
}
// number of the current node to test the line against
nodeNum = tstack_p->nodeNum;
// if it is an area
if ( nodeNum < 0) {
// if can't enter the area
if ( ( areas[-nodeNum].flags & trace.flags ) || ( areas[-nodeNum].travelFlags & trace.travelFlags ) ) {
if ( !trace.lastAreaNum ) {
trace.fraction = 0.0f;
v1 = vec3_origin;
} else {
v1 = end - start;
v2 = tstack_p->start - start;
trace.fraction = v2.Length() / v1.Length();
}
trace.endpos = tstack_p->start;
trace.blockingAreaNum = -nodeNum;
trace.planeNum = tstack_p->planeNum;
// always take the plane with normal facing towards the trace start
plane = &planeList[trace.planeNum];
if ( v1 * plane->Normal() > 0.0f ) {
trace.planeNum ^= 1;
}
return true;
}
trace.lastAreaNum = -nodeNum;
if ( trace.numAreas < trace.maxAreas ) {
if ( trace.areas ) {
trace.areas[trace.numAreas] = -nodeNum;
}
if ( trace.points ) {
trace.points[trace.numAreas] = tstack_p->start;
}
trace.numAreas++;
}
continue;
}
// if it is a solid leaf
if ( !nodeNum ) {
if ( !trace.lastAreaNum ) {
trace.fraction = 0.0f;
v1 = vec3_origin;
} else {
v1 = end - start;
v2 = tstack_p->start - start;
trace.fraction = v2.Length() / v1.Length();
}
trace.endpos = tstack_p->start;
trace.blockingAreaNum = 0; // hit solid leaf
trace.planeNum = tstack_p->planeNum;
// always take the plane with normal facing towards the trace start
plane = &planeList[trace.planeNum];
if ( v1 * plane->Normal() > 0.0f ) {
trace.planeNum ^= 1;
}
if ( !trace.lastAreaNum && trace.getOutOfSolid ) {
continue;
}
else {
return true;
}
}
// the node to test against
node = &nodes[nodeNum];
// start point of current line to test against node
cur_start = tstack_p->start;
// end point of the current line to test against node
cur_end = tstack_p->end;
// the current node plane
plane = &planeList[node->planeNum];
front = plane->Distance( cur_start );
back = plane->Distance( cur_end );
// if the whole to be traced line is totally at the front of this node
// only go down the tree with the front child
if ( front >= -ON_EPSILON && back >= -ON_EPSILON ) {
// keep the current start and end point on the stack and go down the tree with the front child
tstack_p->nodeNum = node->children[0];
tstack_p++;
if ( tstack_p >= &tracestack[MAX_AAS_TREE_DEPTH] ) {
common->Error("idAASFileLocal::Trace: stack overflow\n" );
return false;
}
}
// if the whole to be traced line is totally at the back of this node
// only go down the tree with the back child
else if ( front < ON_EPSILON && back < ON_EPSILON ) {
// keep the current start and end point on the stack and go down the tree with the back child
tstack_p->nodeNum = node->children[1];
tstack_p++;
if ( tstack_p >= &tracestack[MAX_AAS_TREE_DEPTH] ) {
common->Error("idAASFileLocal::Trace: stack overflow\n" );
return false;
}
}
// go down the tree both at the front and back of the node
else {
tmpPlaneNum = tstack_p->planeNum;
// calculate the hit point with the node plane
// put the cross point TRACEPLANE_EPSILON on the near side
if (front < 0) {
frac = (front + TRACEPLANE_EPSILON) / ( front - back );
}
else {
frac = (front - TRACEPLANE_EPSILON) / ( front - back );
}
if (frac < 0) {
frac = 0.001f; //0
}
else if (frac > 1) {
frac = 0.999f; //1
}
cur_mid = cur_start + ( cur_end - cur_start ) * frac;
// side the front part of the line is on
side = front < 0;
// first put the end part of the line on the stack (back side)
tstack_p->start = cur_mid;
tstack_p->planeNum = node->planeNum;
tstack_p->nodeNum = node->children[!side];
tstack_p++;
if ( tstack_p >= &tracestack[MAX_AAS_TREE_DEPTH] ) {
common->Error("idAASFileLocal::Trace: stack overflow\n" );
return false;
}
// now put the part near the start of the line on the stack so we will
// continue with that part first.
tstack_p->start = cur_start;
tstack_p->end = cur_mid;
tstack_p->planeNum = tmpPlaneNum;
tstack_p->nodeNum = node->children[side];
tstack_p++;
if ( tstack_p >= &tracestack[MAX_AAS_TREE_DEPTH] ) {
common->Error("idAASFileLocal::Trace: stack overflow\n" );
return false;
}
}
}
return false;
}
/*
============
idAASLocal::AreaContentsTravelFlags
============
*/
int idAASFileLocal::AreaContentsTravelFlags( int areaNum ) const {
if ( areas[areaNum].contents & AREACONTENTS_WATER ) {
return TFL_WATER;
}
return TFL_AIR;
}
/*
============
idAASFileLocal::MaxTreeDepth_r
============
*/
void idAASFileLocal::MaxTreeDepth_r( int nodeNum, int &depth, int &maxDepth ) const {
const aasNode_t *node;
if ( nodeNum <= 0 ) {
return;
}
depth++;
if ( depth > maxDepth ) {
maxDepth = depth;
}
node = &nodes[nodeNum];
MaxTreeDepth_r( node->children[0], depth, maxDepth );
MaxTreeDepth_r( node->children[1], depth, maxDepth );
depth--;
}
/*
============
idAASFileLocal::MaxTreeDepth
============
*/
int idAASFileLocal::MaxTreeDepth() const {
int depth, maxDepth;
depth = maxDepth = 0;
MaxTreeDepth_r( 1, depth, maxDepth );
return maxDepth;
}

343
neo/amplitude/amplitude.cpp Normal file
View File

@@ -0,0 +1,343 @@
/*
===========================================================================
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.
===========================================================================
*/
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
static const int SAMPLE_RATE = 60;
enum errorCodes_t {
E_OK = 0,
E_ARGS,
E_OPEN_IN,
E_OPEN_OUT,
E_PROCESSING
};
struct chunk_t {
unsigned int id;
unsigned int size;
unsigned int offset;
};
static unsigned short FORMAT_PCM = 0x0001;
struct format_t {
unsigned short formatTag;
unsigned short numChannels;
unsigned int samplesPerSec;
unsigned int avgBytesPerSec;
unsigned short sampleSize;
unsigned short bitsPerSample;
};
#define SwapBytes( x, y ) { unsigned char t = (x); (x) = (y); (y) = t; }
template<class type> static void Swap( type &c ) {
if ( sizeof( type ) == 1 ) {
} else if ( sizeof( type ) == 2 ) {
unsigned char * b = (unsigned char *)&c;
SwapBytes( b[0], b[1] );
} else if ( sizeof( type ) == 4 ) {
unsigned char * b = (unsigned char *)&c;
SwapBytes( b[0], b[3] );
SwapBytes( b[1], b[2] );
} else if ( sizeof( type ) == 8 ) {
unsigned char * b = (unsigned char *)&c;
SwapBytes( b[0], b[7] );
SwapBytes( b[1], b[6]);
SwapBytes( b[2], b[5] );
SwapBytes( b[3], b[4] );
} else {
int * null = 0;
c = *null;
}
}
int WAVE_ReadHeader( FILE * f ) {
struct header_t {
unsigned int id;
unsigned int size;
unsigned int format;
} header;
fread( &header, sizeof( header ), 1, f );
Swap( header.id );
Swap( header.format );
if ( header.id != 'RIFF' || header.format != 'WAVE' || header.size < 4 ) {
return 0;
}
return header.size;
}
int WAVE_ReadChunks( FILE * f, unsigned int fileSize, chunk_t * chunks, int maxChunks ) {
unsigned int offset = ftell( f );
int numChunks = 0;
while ( offset < fileSize ) {
struct chuckHeader_t {
unsigned int id;
unsigned int size;
} chunkHeader;
if ( fread( &chunkHeader, sizeof( chunkHeader ), 1, f ) != 1 ) {
return numChunks;
}
Swap( chunkHeader.id );
offset += sizeof( chunkHeader );
if ( numChunks == maxChunks ) {
return maxChunks + 1;
}
chunks[numChunks].id = chunkHeader.id;
chunks[numChunks].size = chunkHeader.size;
chunks[numChunks].offset = offset;
numChunks++;
offset += chunkHeader.size;
fseek( f, offset, SEEK_SET );
}
return numChunks;
}
bool Process( FILE * in, FILE * out ) {
int headerSize = WAVE_ReadHeader( in );
if ( headerSize == 0 ) {
printf( "Header invalid\n" );
return false;
}
static const int MAX_CHUNKS = 32;
chunk_t chunks[MAX_CHUNKS] = {};
int numChunks = WAVE_ReadChunks( in, headerSize + 8, chunks, MAX_CHUNKS );
if ( numChunks == 0 ) {
printf( "No chunks\n" );
return false;
}
if ( numChunks > MAX_CHUNKS ) {
printf( "Too many chunks\n" );
return false;
}
format_t format;
bool foundFormat = false;
unsigned int dataOffset = 0;
unsigned int dataSize = 0;
for ( int i = 0; i < numChunks; i++ ) {
if ( chunks[i].id == 'fmt ' ) {
if ( foundFormat ) {
printf( "Found multiple format chunks\n" );
return false;
}
if ( chunks[i].size < sizeof( format ) ) {
printf( "Format chunk too small\n" );
return false;
}
fseek( in, chunks[i].offset, SEEK_SET );
fread( &format, sizeof( format ), 1, in );
foundFormat = true;
}
if ( chunks[i].id == 'data' ) {
if ( dataOffset > 0 ) {
printf( "Found multiple data chunks\n" );
return false;
}
dataOffset = chunks[i].offset;
dataSize = chunks[i].size;
}
}
if ( dataOffset == 0 ) {
printf( "Colud not find data chunk\n" );
return false;
}
if ( !foundFormat ) {
printf( "Could not find fmt chunk\n" );
return false;
}
if ( format.formatTag != FORMAT_PCM ) {
printf( "Only PCM files supported (%d)\n", format.formatTag );
return false;
}
if ( format.bitsPerSample != 8 && format.bitsPerSample != 16 ) {
printf( "Only 8 or 16 bit files supported (%d)\n", format.bitsPerSample );
return false;
}
if ( format.numChannels != 1 && format.numChannels != 2 ) {
printf( "Only stereo or mono files supported (%d)\n", format.numChannels );
return false;
}
unsigned short expectedSampleSize = format.numChannels * format.bitsPerSample / 8;
if ( format.sampleSize != expectedSampleSize ) {
printf( "Invalid sampleSize (%d, expected %d)\n", format.sampleSize, expectedSampleSize );
return false;
}
unsigned int numSamples = dataSize / expectedSampleSize;
void * inputData = malloc( dataSize );
if ( inputData == NULL ) {
printf( "Out of memory\n" );
return false;
}
fseek( in, dataOffset, SEEK_SET );
fread( inputData, dataSize, 1, in );
int numOutputSamples = 1 + ( numSamples * SAMPLE_RATE / format.samplesPerSec );
float * min = (float *)malloc( numOutputSamples * sizeof( float ) );
float * max = (float *)malloc( numOutputSamples * sizeof( float ) );
unsigned char * outputData = (unsigned char *)malloc( numOutputSamples );
if ( min == NULL || max == NULL || outputData == NULL ) {
printf( "Out of memory\n" );
free( inputData );
free( min );
free( max );
free( outputData );
return false;
}
for ( int i = 0; i < numOutputSamples; i++ ) {
max[i] = -1.0f;
min[i] = 1.0f;
}
if ( format.bitsPerSample == 16 ) {
short * sdata = (short *)inputData;
if ( format.numChannels == 1 ) {
for ( unsigned int i = 0; i < numSamples; i++ ) {
unsigned int index = i * SAMPLE_RATE / format.samplesPerSec;
float fdata = (float)sdata[i] / 32767.0f;
min[index] = __min( min[index], fdata );
max[index] = __max( max[index], fdata );
}
} else {
unsigned int j = 0;
for ( unsigned int i = 0; i < numSamples; i++ ) {
unsigned int index = i * SAMPLE_RATE / format.samplesPerSec;
for ( unsigned int c = 0; c < format.numChannels; c++ ) {
float fdata = (float)sdata[j++] / 32767.0f;
min[index] = __min( min[index], fdata );
max[index] = __max( max[index], fdata );
}
}
}
} else {
unsigned char * bdata = (unsigned char *)inputData;
if ( format.numChannels == 1 ) {
for ( unsigned int i = 0; i < numSamples; i++ ) {
unsigned int index = i * SAMPLE_RATE / format.samplesPerSec;
float fdata = ( (float)bdata[i] - 128.0f ) / 127.0f;
min[index] = __min( min[index], fdata );
max[index] = __max( max[index], fdata );
}
} else {
unsigned int j = 0;
for ( unsigned int i = 0; i < numSamples; i++ ) {
unsigned int index = i * SAMPLE_RATE / format.samplesPerSec;
for ( unsigned int c = 0; c < format.numChannels; c++ ) {
float fdata = ( (float)bdata[j++] - 128.0f ) / 127.0f;
min[index] = __min( min[index], fdata );
max[index] = __max( max[index], fdata );
}
}
}
}
for ( int i = 0; i < numOutputSamples; i++ ) {
float amp = atan( max[i] - min[i] ) / 0.7853981633974483f;
int o = (int)( amp * 255.0f );
if ( o > 255 ) {
outputData[i] = 255;
} else if ( o < 0 ) {
outputData[i] = 0;
} else {
outputData[i] = (unsigned char)o;
}
}
fwrite( outputData, numOutputSamples, 1, out );
free( inputData );
free( min );
free( max );
free( outputData );
printf( "Success\n" );
return true;
}
int main(int argc, char * argv[]) {
if ( argc < 2 ) {
printf( "Usage: %s <wav>\n", argv[0] );
return E_ARGS;
}
const char * inputFileName = argv[1];
printf( "Processing %s: ", inputFileName );
FILE * in = NULL;
if ( fopen_s( &in, inputFileName, "rb" ) != 0 ) {
printf( "Could not open input file\n" );
return E_OPEN_IN;
}
char outputFileName[1024] = {0};
if ( strcpy_s( outputFileName, inputFileName ) != 0 ) {
printf( "Filename too long\n" );
return E_ARGS;
}
char * dot = strrchr( outputFileName, '.' );
if ( dot == NULL ) {
dot = outputFileName + strlen( outputFileName );
}
if ( strcpy_s( dot, sizeof( outputFileName ) - ( dot - outputFileName ), ".amp" ) != 0 ) {
printf( "Filename too long\n" );
return E_ARGS;
}
FILE * out = NULL;
if ( fopen_s( &out, outputFileName, "wb" ) != 0 ) {
printf( "Could not open output file %s\n", outputFileName );
return E_OPEN_OUT;
}
bool success = Process( in, out );
fclose( in );
fclose( out );
if ( !success ) {
remove( outputFileName );
return E_PROCESSING;
}
return E_OK;
}

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Retail|Win32">
<Configuration>Retail</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="amplitude.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{57DBA8C7-2BBF-44CA-8189-600F90DC29DD}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>amplitude</RootNamespace>
<SccProjectName>
</SccProjectName>
<SccAuxPath>
</SccAuxPath>
<SccLocalPath>
</SccLocalPath>
<SccProvider>
</SccProvider>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Retail|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Retail|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Retail|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Retail|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="amplitude.cpp" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
}

150
neo/cm/CollisionModel.h Normal file
View File

@@ -0,0 +1,150 @@
/*
===========================================================================
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 __COLLISIONMODELMANAGER_H__
#define __COLLISIONMODELMANAGER_H__
/*
===============================================================================
Trace model vs. polygonal model collision detection.
Short translations are the least expensive. Retrieving contact points is
about as cheap as a short translation. Position tests are more expensive
and rotations are most expensive.
There is no position test at the start of a translation or rotation. In other
words if a translation with start != end or a rotation with angle != 0 starts
in solid, this goes unnoticed and the collision result is undefined.
A translation with start == end or a rotation with angle == 0 performs
a position test and fills in the trace_t structure accordingly.
===============================================================================
*/
// contact type
typedef enum {
CONTACT_NONE, // no contact
CONTACT_EDGE, // trace model edge hits model edge
CONTACT_MODELVERTEX, // model vertex hits trace model polygon
CONTACT_TRMVERTEX // trace model vertex hits model polygon
} contactType_t;
// contact info
typedef struct {
contactType_t type; // contact type
idVec3 point; // point of contact
idVec3 normal; // contact plane normal
float dist; // contact plane distance
int contents; // contents at other side of surface
const idMaterial * material; // surface material
int modelFeature; // contact feature on model
int trmFeature; // contact feature on trace model
int entityNum; // entity the contact surface is a part of
int id; // id of clip model the contact surface is part of
} contactInfo_t;
// trace result
typedef struct trace_s {
float fraction; // fraction of movement completed, 1.0 = didn't hit anything
idVec3 endpos; // final position of trace model
idMat3 endAxis; // final axis of trace model
contactInfo_t c; // contact information, only valid if fraction < 1.0
} trace_t;
typedef int cmHandle_t;
#define CM_CLIP_EPSILON 0.25f // always stay this distance away from any model
#define CM_BOX_EPSILON 1.0f // should always be larger than clip epsilon
#define CM_MAX_TRACE_DIST 4096.0f // maximum distance a trace model may be traced, point traces are unlimited
class idCollisionModelManager {
public:
virtual ~idCollisionModelManager() {}
// Loads collision models from a map file.
virtual void LoadMap( const idMapFile *mapFile ) = 0;
// Frees all the collision models.
virtual void FreeMap() = 0;
virtual void Preload( const char *mapName ) = 0;
// Gets the clip handle for a model.
virtual cmHandle_t LoadModel( const char *modelName ) = 0;
// Sets up a trace model for collision with other trace models.
virtual cmHandle_t SetupTrmModel( const idTraceModel &trm, const idMaterial *material ) = 0;
// Creates a trace model from a collision model, returns true if succesfull.
virtual bool TrmFromModel( const char *modelName, idTraceModel &trm ) = 0;
// Gets the name of a model.
virtual const char * GetModelName( cmHandle_t model ) const = 0;
// Gets the bounds of a model.
virtual bool GetModelBounds( cmHandle_t model, idBounds &bounds ) const = 0;
// Gets all contents flags of brushes and polygons of a model ored together.
virtual bool GetModelContents( cmHandle_t model, int &contents ) const = 0;
// Gets a vertex of a model.
virtual bool GetModelVertex( cmHandle_t model, int vertexNum, idVec3 &vertex ) const = 0;
// Gets an edge of a model.
virtual bool GetModelEdge( cmHandle_t model, int edgeNum, idVec3 &start, idVec3 &end ) const = 0;
// Gets a polygon of a model.
virtual bool GetModelPolygon( cmHandle_t model, int polygonNum, idFixedWinding &winding ) const = 0;
// Translates a trace model and reports the first collision if any.
virtual void Translation( trace_t *results, const idVec3 &start, const idVec3 &end,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) = 0;
// Rotates a trace model and reports the first collision if any.
virtual void Rotation( trace_t *results, const idVec3 &start, const idRotation &rotation,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) = 0;
// Returns the contents touched by the trace model or 0 if the trace model is in free space.
virtual int Contents( const idVec3 &start,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) = 0;
// Stores all contact points of the trace model with the model, returns the number of contacts.
virtual int Contacts( contactInfo_t *contacts, const int maxContacts, const idVec3 &start, const idVec6 &dir, const float depth,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) = 0;
// Tests collision detection.
virtual void DebugOutput( const idVec3 &origin ) = 0;
// Draws a model.
virtual void DrawModel( cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis,
const idVec3 &viewOrigin, const float radius ) = 0;
// Prints model information, use -1 handle for accumulated model info.
virtual void ModelInfo( cmHandle_t model ) = 0;
// Lists all loaded models.
virtual void ListModels() = 0;
// Writes a collision model file for the given map entity.
virtual bool WriteCollisionModelForMapEntity( const idMapEntity *mapEnt, const char *filename, const bool testTraceModel = true ) = 0;
};
extern idCollisionModelManager * collisionModelManager;
#endif /* !__COLLISIONMODELMANAGER_H__ */

View File

@@ -0,0 +1,76 @@
/*
===========================================================================
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.
===========================================================================
*/
/*
===============================================================================
Trace model vs. polygonal model collision detection.
===============================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "CollisionModel_local.h"
/*
===============================================================================
Retrieving contacts
===============================================================================
*/
/*
==================
idCollisionModelManagerLocal::Contacts
==================
*/
int idCollisionModelManagerLocal::Contacts( contactInfo_t *contacts, const int maxContacts, const idVec3 &start, const idVec6 &dir, const float depth,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &origin, const idMat3 &modelAxis ) {
trace_t results;
idVec3 end;
// same as Translation but instead of storing the first collision we store all collisions as contacts
idCollisionModelManagerLocal::getContacts = true;
idCollisionModelManagerLocal::contacts = contacts;
idCollisionModelManagerLocal::maxContacts = maxContacts;
idCollisionModelManagerLocal::numContacts = 0;
end = start + dir.SubVec3(0) * depth;
idCollisionModelManagerLocal::Translation( &results, start, end, trm, trmAxis, contentMask, model, origin, modelAxis );
if ( dir.SubVec3(1).LengthSqr() != 0.0f ) {
// FIXME: rotational contacts
}
idCollisionModelManagerLocal::getContacts = false;
idCollisionModelManagerLocal::maxContacts = 0;
return idCollisionModelManagerLocal::numContacts;
}

View File

@@ -0,0 +1,636 @@
/*
===========================================================================
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.
===========================================================================
*/
/*
===============================================================================
Trace model vs. polygonal model collision detection.
===============================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "CollisionModel_local.h"
/*
===============================================================================
Contents test
===============================================================================
*/
/*
================
idCollisionModelManagerLocal::TestTrmVertsInBrush
returns true if any of the trm vertices is inside the brush
================
*/
bool idCollisionModelManagerLocal::TestTrmVertsInBrush( cm_traceWork_t *tw, cm_brush_t *b ) {
int i, j, numVerts, bestPlane;
float d, bestd;
idVec3 *p;
if ( b->checkcount == idCollisionModelManagerLocal::checkCount ) {
return false;
}
b->checkcount = idCollisionModelManagerLocal::checkCount;
if ( !(b->contents & tw->contents) ) {
return false;
}
// if the brush bounds don't intersect the trace bounds
if ( !b->bounds.IntersectsBounds( tw->bounds ) ) {
return false;
}
if ( tw->pointTrace ) {
numVerts = 1;
}
else {
numVerts = tw->numVerts;
}
for ( j = 0; j < numVerts; j++ ) {
p = &tw->vertices[j].p;
// see if the point is inside the brush
bestPlane = 0;
bestd = -idMath::INFINITY;
for ( i = 0; i < b->numPlanes; i++ ) {
d = b->planes[i].Distance( *p );
if ( d >= 0.0f ) {
break;
}
if ( d > bestd ) {
bestd = d;
bestPlane = i;
}
}
if ( i >= b->numPlanes ) {
tw->trace.fraction = 0.0f;
tw->trace.c.type = CONTACT_TRMVERTEX;
tw->trace.c.normal = b->planes[bestPlane].Normal();
tw->trace.c.dist = b->planes[bestPlane].Dist();
tw->trace.c.contents = b->contents;
tw->trace.c.material = b->material;
tw->trace.c.point = *p;
tw->trace.c.modelFeature = 0;
tw->trace.c.trmFeature = j;
return true;
}
}
return false;
}
/*
================
CM_SetTrmEdgeSidedness
================
*/
#define CM_SetTrmEdgeSidedness( edge, bpl, epl, bitNum ) { \
const int mask = 1 << bitNum; \
if ( ( edge->sideSet & mask ) == 0 ) { \
const float fl = (bpl).PermutedInnerProduct( epl ); \
edge->side = ( edge->side & ~mask ) | ( ( fl < 0.0f ) ? mask : 0 ); \
edge->sideSet |= mask; \
} \
}
/*
================
CM_SetTrmPolygonSidedness
================
*/
#define CM_SetTrmPolygonSidedness( v, plane, bitNum ) { \
const int mask = 1 << bitNum; \
if ( ( (v)->sideSet & mask ) == 0 ) { \
const float fl = plane.Distance( (v)->p ); \
(v)->side = ( (v)->side & ~mask ) | ( ( fl < 0.0f ) ? mask : 0 ); \
(v)->sideSet |= mask; \
} \
}
/*
================
idCollisionModelManagerLocal::TestTrmInPolygon
returns true if the trm intersects the polygon
================
*/
bool idCollisionModelManagerLocal::TestTrmInPolygon( cm_traceWork_t *tw, cm_polygon_t *p ) {
int i, j, k, edgeNum, flip, trmEdgeNum, bitNum, bestPlane;
int sides[MAX_TRACEMODEL_VERTS];
float d, bestd;
cm_trmEdge_t *trmEdge;
cm_edge_t *edge;
cm_vertex_t *v, *v1, *v2;
// if already checked this polygon
if ( p->checkcount == idCollisionModelManagerLocal::checkCount ) {
return false;
}
p->checkcount = idCollisionModelManagerLocal::checkCount;
// if this polygon does not have the right contents behind it
if ( !(p->contents & tw->contents) ) {
return false;
}
// if the polygon bounds don't intersect the trace bounds
if ( !p->bounds.IntersectsBounds( tw->bounds ) ) {
return false;
}
// bounds should cross polygon plane
switch( tw->bounds.PlaneSide( p->plane ) ) {
case PLANESIDE_CROSS:
break;
case PLANESIDE_FRONT:
if ( tw->model->isConvex ) {
tw->quickExit = true;
return true;
}
default:
return false;
}
// if the trace model is convex
if ( tw->isConvex ) {
// test if any polygon vertices are inside the trm
for ( i = 0; i < p->numEdges; i++ ) {
edgeNum = p->edges[i];
edge = tw->model->edges + abs(edgeNum);
// if this edge is already tested
if ( edge->checkcount == idCollisionModelManagerLocal::checkCount ) {
continue;
}
for ( j = 0; j < 2; j++ ) {
v = &tw->model->vertices[edge->vertexNum[j]];
// if this vertex is already tested
if ( v->checkcount == idCollisionModelManagerLocal::checkCount ) {
continue;
}
bestPlane = 0;
bestd = -idMath::INFINITY;
for ( k = 0; k < tw->numPolys; k++ ) {
d = tw->polys[k].plane.Distance( v->p );
if ( d >= 0.0f ) {
break;
}
if ( d > bestd ) {
bestd = d;
bestPlane = k;
}
}
if ( k >= tw->numPolys ) {
tw->trace.fraction = 0.0f;
tw->trace.c.type = CONTACT_MODELVERTEX;
tw->trace.c.normal = -tw->polys[bestPlane].plane.Normal();
tw->trace.c.dist = -tw->polys[bestPlane].plane.Dist();
tw->trace.c.contents = p->contents;
tw->trace.c.material = p->material;
tw->trace.c.point = v->p;
tw->trace.c.modelFeature = edge->vertexNum[j];
tw->trace.c.trmFeature = 0;
return true;
}
}
}
}
for ( i = 0; i < p->numEdges; i++ ) {
edgeNum = p->edges[i];
edge = tw->model->edges + abs(edgeNum);
// reset sidedness cache if this is the first time we encounter this edge
if ( edge->checkcount != idCollisionModelManagerLocal::checkCount ) {
edge->sideSet = 0;
}
// pluecker coordinate for edge
tw->polygonEdgePlueckerCache[i].FromLine( tw->model->vertices[edge->vertexNum[0]].p,
tw->model->vertices[edge->vertexNum[1]].p );
v = &tw->model->vertices[edge->vertexNum[INT32_SIGNBITSET( edgeNum )]];
// reset sidedness cache if this is the first time we encounter this vertex
if ( v->checkcount != idCollisionModelManagerLocal::checkCount ) {
v->sideSet = 0;
}
v->checkcount = idCollisionModelManagerLocal::checkCount;
}
// get side of polygon for each trm vertex
for ( i = 0; i < tw->numVerts; i++ ) {
d = p->plane.Distance( tw->vertices[i].p );
sides[i] = d < 0.0f ? -1 : 1;
}
// test if any trm edges go through the polygon
for ( i = 1; i <= tw->numEdges; i++ ) {
// if the trm edge does not cross the polygon plane
if ( sides[tw->edges[i].vertexNum[0]] == sides[tw->edges[i].vertexNum[1]] ) {
continue;
}
// check from which side to which side the trm edge goes
flip = INT32_SIGNBITSET( sides[tw->edges[i].vertexNum[0]] );
// test if trm edge goes through the polygon between the polygon edges
for ( j = 0; j < p->numEdges; j++ ) {
edgeNum = p->edges[j];
edge = tw->model->edges + abs(edgeNum);
#if 1
CM_SetTrmEdgeSidedness( edge, tw->edges[i].pl, tw->polygonEdgePlueckerCache[j], i );
if ( INT32_SIGNBITSET( edgeNum ) ^ ( ( edge->side >> i ) & 1 ) ^ flip ) {
break;
}
#else
d = tw->edges[i].pl.PermutedInnerProduct( tw->polygonEdgePlueckerCache[j] );
if ( flip ) {
d = -d;
}
if ( edgeNum > 0 ) {
if ( d <= 0.0f ) {
break;
}
}
else {
if ( d >= 0.0f ) {
break;
}
}
#endif
}
if ( j >= p->numEdges ) {
tw->trace.fraction = 0.0f;
tw->trace.c.type = CONTACT_EDGE;
tw->trace.c.normal = p->plane.Normal();
tw->trace.c.dist = p->plane.Dist();
tw->trace.c.contents = p->contents;
tw->trace.c.material = p->material;
tw->trace.c.point = tw->vertices[tw->edges[i].vertexNum[ !flip ]].p;
tw->trace.c.modelFeature = *reinterpret_cast<int *>(&p);
tw->trace.c.trmFeature = i;
return true;
}
}
// test if any polygon edges go through the trm polygons
for ( i = 0; i < p->numEdges; i++ ) {
edgeNum = p->edges[i];
edge = tw->model->edges + abs(edgeNum);
if ( edge->checkcount == idCollisionModelManagerLocal::checkCount ) {
continue;
}
edge->checkcount = idCollisionModelManagerLocal::checkCount;
for ( j = 0; j < tw->numPolys; j++ ) {
#if 1
v1 = tw->model->vertices + edge->vertexNum[0];
CM_SetTrmPolygonSidedness( v1, tw->polys[j].plane, j );
v2 = tw->model->vertices + edge->vertexNum[1];
CM_SetTrmPolygonSidedness( v2, tw->polys[j].plane, j );
// if the polygon edge does not cross the trm polygon plane
if ( !(((v1->side ^ v2->side) >> j) & 1) ) {
continue;
}
flip = (v1->side >> j) & 1;
#else
float d1, d2;
v1 = tw->model->vertices + edge->vertexNum[0];
d1 = tw->polys[j].plane.Distance( v1->p );
v2 = tw->model->vertices + edge->vertexNum[1];
d2 = tw->polys[j].plane.Distance( v2->p );
// if the polygon edge does not cross the trm polygon plane
if ( (d1 >= 0.0f && d2 >= 0.0f) || (d1 <= 0.0f && d2 <= 0.0f) ) {
continue;
}
flip = false;
if ( d1 < 0.0f ) {
flip = true;
}
#endif
// test if polygon edge goes through the trm polygon between the trm polygon edges
for ( k = 0; k < tw->polys[j].numEdges; k++ ) {
trmEdgeNum = tw->polys[j].edges[k];
trmEdge = tw->edges + abs(trmEdgeNum);
#if 1
bitNum = abs(trmEdgeNum);
CM_SetTrmEdgeSidedness( edge, trmEdge->pl, tw->polygonEdgePlueckerCache[i], bitNum );
if ( INT32_SIGNBITSET( trmEdgeNum ) ^ ( ( edge->side >> bitNum ) & 1 ) ^ flip ) {
break;
}
#else
d = trmEdge->pl.PermutedInnerProduct( tw->polygonEdgePlueckerCache[i] );
if ( flip ) {
d = -d;
}
if ( trmEdgeNum > 0 ) {
if ( d <= 0.0f ) {
break;
}
}
else {
if ( d >= 0.0f ) {
break;
}
}
#endif
}
if ( k >= tw->polys[j].numEdges ) {
tw->trace.fraction = 0.0f;
tw->trace.c.type = CONTACT_EDGE;
tw->trace.c.normal = -tw->polys[j].plane.Normal();
tw->trace.c.dist = -tw->polys[j].plane.Dist();
tw->trace.c.contents = p->contents;
tw->trace.c.material = p->material;
tw->trace.c.point = tw->model->vertices[edge->vertexNum[ !flip ]].p;
tw->trace.c.modelFeature = edgeNum;
tw->trace.c.trmFeature = j;
return true;
}
}
}
return false;
}
/*
================
idCollisionModelManagerLocal::PointNode
================
*/
cm_node_t *idCollisionModelManagerLocal::PointNode( const idVec3 &p, cm_model_t *model ) {
cm_node_t *node;
node = model->node;
while ( node->planeType != -1 ) {
if (p[node->planeType] > node->planeDist) {
node = node->children[0];
}
else {
node = node->children[1];
}
assert( node != NULL );
}
return node;
}
/*
================
idCollisionModelManagerLocal::PointContents
================
*/
int idCollisionModelManagerLocal::PointContents( const idVec3 p, cmHandle_t model ) {
int i;
float d;
cm_node_t *node;
cm_brushRef_t *bref;
cm_brush_t *b;
idPlane *plane;
node = idCollisionModelManagerLocal::PointNode( p, idCollisionModelManagerLocal::models[model] );
for ( bref = node->brushes; bref; bref = bref->next ) {
b = bref->b;
// test if the point is within the brush bounds
for ( i = 0; i < 3; i++ ) {
if ( p[i] < b->bounds[0][i] ) {
break;
}
if ( p[i] > b->bounds[1][i] ) {
break;
}
}
if ( i < 3 ) {
continue;
}
// test if the point is inside the brush
plane = b->planes;
for ( i = 0; i < b->numPlanes; i++, plane++ ) {
d = plane->Distance( p );
if ( d >= 0.0f ) {
break;
}
}
if ( i >= b->numPlanes ) {
return b->contents;
}
}
return 0;
}
/*
==================
idCollisionModelManagerLocal::TransformedPointContents
==================
*/
int idCollisionModelManagerLocal::TransformedPointContents( const idVec3 &p, cmHandle_t model, const idVec3 &origin, const idMat3 &modelAxis ) {
idVec3 p_l;
// subtract origin offset
p_l = p - origin;
if ( modelAxis.IsRotated() ) {
p_l *= modelAxis;
}
return idCollisionModelManagerLocal::PointContents( p_l, model );
}
/*
==================
idCollisionModelManagerLocal::ContentsTrm
==================
*/
int idCollisionModelManagerLocal::ContentsTrm( trace_t *results, const idVec3 &start,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) {
int i;
bool model_rotated, trm_rotated;
idMat3 invModelAxis, tmpAxis;
idVec3 dir;
ALIGN16( cm_traceWork_t tw );
// fast point case
if ( !trm || ( trm->bounds[1][0] - trm->bounds[0][0] <= 0.0f &&
trm->bounds[1][1] - trm->bounds[0][1] <= 0.0f &&
trm->bounds[1][2] - trm->bounds[0][2] <= 0.0f ) ) {
results->c.contents = idCollisionModelManagerLocal::TransformedPointContents( start, model, modelOrigin, modelAxis );
results->fraction = ( results->c.contents == 0 );
results->endpos = start;
results->endAxis = trmAxis;
return results->c.contents;
}
idCollisionModelManagerLocal::checkCount++;
tw.trace.fraction = 1.0f;
tw.trace.c.contents = 0;
tw.trace.c.type = CONTACT_NONE;
tw.contents = contentMask;
tw.isConvex = true;
tw.rotation = false;
tw.positionTest = true;
tw.pointTrace = false;
tw.quickExit = false;
tw.numContacts = 0;
tw.model = idCollisionModelManagerLocal::models[model];
tw.start = start - modelOrigin;
tw.end = tw.start;
model_rotated = modelAxis.IsRotated();
if ( model_rotated ) {
invModelAxis = modelAxis.Transpose();
}
// setup trm structure
idCollisionModelManagerLocal::SetupTrm( &tw, trm );
trm_rotated = trmAxis.IsRotated();
// calculate vertex positions
if ( trm_rotated ) {
for ( i = 0; i < tw.numVerts; i++ ) {
// rotate trm around the start position
tw.vertices[i].p *= trmAxis;
}
}
for ( i = 0; i < tw.numVerts; i++ ) {
// set trm at start position
tw.vertices[i].p += tw.start;
}
if ( model_rotated ) {
for ( i = 0; i < tw.numVerts; i++ ) {
// rotate trm around model instead of rotating the model
tw.vertices[i].p *= invModelAxis;
}
}
// add offset to start point
if ( trm_rotated ) {
dir = trm->offset * trmAxis;
tw.start += dir;
tw.end += dir;
} else {
tw.start += trm->offset;
tw.end += trm->offset;
}
if ( model_rotated ) {
// rotate trace instead of model
tw.start *= invModelAxis;
tw.end *= invModelAxis;
}
// setup trm vertices
tw.size.Clear();
for ( i = 0; i < tw.numVerts; i++ ) {
// get axial trm size after rotations
tw.size.AddPoint( tw.vertices[i].p - tw.start );
}
// setup trm edges
for ( i = 1; i <= tw.numEdges; i++ ) {
// edge start, end and pluecker coordinate
tw.edges[i].start = tw.vertices[tw.edges[i].vertexNum[0]].p;
tw.edges[i].end = tw.vertices[tw.edges[i].vertexNum[1]].p;
tw.edges[i].pl.FromLine( tw.edges[i].start, tw.edges[i].end );
}
// setup trm polygons
if ( trm_rotated & model_rotated ) {
tmpAxis = trmAxis * invModelAxis;
for ( i = 0; i < tw.numPolys; i++ ) {
tw.polys[i].plane *= tmpAxis;
}
} else if ( trm_rotated ) {
for ( i = 0; i < tw.numPolys; i++ ) {
tw.polys[i].plane *= trmAxis;
}
} else if ( model_rotated ) {
for ( i = 0; i < tw.numPolys; i++ ) {
tw.polys[i].plane *= invModelAxis;
}
}
for ( i = 0; i < tw.numPolys; i++ ) {
tw.polys[i].plane.FitThroughPoint( tw.edges[abs(tw.polys[i].edges[0])].start );
}
// bounds for full trace, a little bit larger for epsilons
for ( i = 0; i < 3; i++ ) {
if ( tw.start[i] < tw.end[i] ) {
tw.bounds[0][i] = tw.start[i] + tw.size[0][i] - CM_BOX_EPSILON;
tw.bounds[1][i] = tw.end[i] + tw.size[1][i] + CM_BOX_EPSILON;
} else {
tw.bounds[0][i] = tw.end[i] + tw.size[0][i] - CM_BOX_EPSILON;
tw.bounds[1][i] = tw.start[i] + tw.size[1][i] + CM_BOX_EPSILON;
}
if ( idMath::Fabs(tw.size[0][i]) > idMath::Fabs(tw.size[1][i]) ) {
tw.extents[i] = idMath::Fabs( tw.size[0][i] ) + CM_BOX_EPSILON;
} else {
tw.extents[i] = idMath::Fabs( tw.size[1][i] ) + CM_BOX_EPSILON;
}
}
// trace through the model
idCollisionModelManagerLocal::TraceThroughModel( &tw );
*results = tw.trace;
results->fraction = ( results->c.contents == 0 );
results->endpos = start;
results->endAxis = trmAxis;
return results->c.contents;
}
/*
==================
idCollisionModelManagerLocal::Contents
==================
*/
int idCollisionModelManagerLocal::Contents( const idVec3 &start,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) {
trace_t results;
if ( model < 0 || model > idCollisionModelManagerLocal::maxModels || model > MAX_SUBMODELS ) {
common->Printf("idCollisionModelManagerLocal::Contents: invalid model handle\n");
return 0;
}
if ( !idCollisionModelManagerLocal::models || !idCollisionModelManagerLocal::models[model] ) {
common->Printf("idCollisionModelManagerLocal::Contents: invalid model\n");
return 0;
}
return ContentsTrm( &results, start, trm, trmAxis, contentMask, model, modelOrigin, modelAxis );
}

View File

@@ -0,0 +1,489 @@
/*
===========================================================================
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.
===========================================================================
*/
/*
===============================================================================
Trace model vs. polygonal model collision detection.
===============================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "CollisionModel_local.h"
/*
===============================================================================
Visualisation code
===============================================================================
*/
const char *cm_contentsNameByIndex[] = {
"none", // 0
"solid", // 1
"opaque", // 2
"water", // 3
"playerclip", // 4
"monsterclip", // 5
"moveableclip", // 6
"ikclip", // 7
"blood", // 8
"body", // 9
"corpse", // 10
"trigger", // 11
"aas_solid", // 12
"aas_obstacle", // 13
"flashlight_trigger", // 14
NULL
};
int cm_contentsFlagByIndex[] = {
-1, // 0
CONTENTS_SOLID, // 1
CONTENTS_OPAQUE, // 2
CONTENTS_WATER, // 3
CONTENTS_PLAYERCLIP, // 4
CONTENTS_MONSTERCLIP, // 5
CONTENTS_MOVEABLECLIP, // 6
CONTENTS_IKCLIP, // 7
CONTENTS_BLOOD, // 8
CONTENTS_BODY, // 9
CONTENTS_CORPSE, // 10
CONTENTS_TRIGGER, // 11
CONTENTS_AAS_SOLID, // 12
CONTENTS_AAS_OBSTACLE, // 13
CONTENTS_FLASHLIGHT_TRIGGER, // 14
0
};
idCVar cm_drawMask( "cm_drawMask", "none", CVAR_GAME, "collision mask", cm_contentsNameByIndex, idCmdSystem::ArgCompletion_String<cm_contentsNameByIndex> );
idCVar cm_drawColor( "cm_drawColor", "1 0 0 .5", CVAR_GAME, "color used to draw the collision models" );
idCVar cm_drawFilled( "cm_drawFilled", "0", CVAR_GAME | CVAR_BOOL, "draw filled polygons" );
idCVar cm_drawInternal( "cm_drawInternal", "1", CVAR_GAME | CVAR_BOOL, "draw internal edges green" );
idCVar cm_drawNormals( "cm_drawNormals", "0", CVAR_GAME | CVAR_BOOL, "draw polygon and edge normals" );
idCVar cm_backFaceCull( "cm_backFaceCull", "0", CVAR_GAME | CVAR_BOOL, "cull back facing polygons" );
idCVar cm_debugCollision( "cm_debugCollision", "0", CVAR_GAME | CVAR_BOOL, "debug the collision detection" );
static idVec4 cm_color;
/*
================
idCollisionModelManagerLocal::ContentsFromString
================
*/
int idCollisionModelManagerLocal::ContentsFromString( const char *string ) const {
int i, contents = 0;
idLexer src( string, idStr::Length( string ), "ContentsFromString" );
idToken token;
while( src.ReadToken( &token ) ) {
if ( token == "," ) {
continue;
}
for ( i = 1; cm_contentsNameByIndex[i] != NULL; i++ ) {
if ( token.Icmp( cm_contentsNameByIndex[i] ) == 0 ) {
contents |= cm_contentsFlagByIndex[i];
break;
}
}
}
return contents;
}
/*
================
idCollisionModelManagerLocal::StringFromContents
================
*/
const char *idCollisionModelManagerLocal::StringFromContents( const int contents ) const {
int i, length = 0;
static char contentsString[MAX_STRING_CHARS];
contentsString[0] = '\0';
for ( i = 1; cm_contentsFlagByIndex[i] != 0; i++ ) {
if ( contents & cm_contentsFlagByIndex[i] ) {
if ( length != 0 ) {
length += idStr::snPrintf( contentsString + length, sizeof( contentsString ) - length, "," );
}
length += idStr::snPrintf( contentsString + length, sizeof( contentsString ) - length, cm_contentsNameByIndex[i] );
}
}
return contentsString;
}
/*
================
idCollisionModelManagerLocal::DrawEdge
================
*/
void idCollisionModelManagerLocal::DrawEdge( cm_model_t *model, int edgeNum, const idVec3 &origin, const idMat3 &axis ) {
int side;
cm_edge_t *edge;
idVec3 start, end, mid;
bool isRotated;
isRotated = axis.IsRotated();
edge = model->edges + abs(edgeNum);
side = edgeNum < 0;
start = model->vertices[edge->vertexNum[side]].p;
end = model->vertices[edge->vertexNum[!side]].p;
if ( isRotated ) {
start *= axis;
end *= axis;
}
start += origin;
end += origin;
if ( edge->internal ) {
if ( cm_drawInternal.GetBool() ) {
common->RW()->DebugArrow( colorGreen, start, end, 1 );
}
} else {
if ( edge->numUsers > 2 ) {
common->RW()->DebugArrow( colorBlue, start, end, 1 );
} else {
common->RW()->DebugArrow( cm_color, start, end, 1 );
}
}
if ( cm_drawNormals.GetBool() ) {
mid = (start + end) * 0.5f;
if ( isRotated ) {
end = mid + 5 * (axis * edge->normal);
} else {
end = mid + 5 * edge->normal;
}
common->RW()->DebugArrow( colorCyan, mid, end, 1 );
}
}
/*
================
idCollisionModelManagerLocal::DrawPolygon
================
*/
void idCollisionModelManagerLocal::DrawPolygon( cm_model_t *model, cm_polygon_t *p, const idVec3 &origin, const idMat3 &axis, const idVec3 &viewOrigin ) {
int i, edgeNum;
cm_edge_t *edge;
idVec3 center, end, dir;
if ( cm_backFaceCull.GetBool() ) {
edgeNum = p->edges[0];
edge = model->edges + abs(edgeNum);
dir = model->vertices[edge->vertexNum[0]].p - viewOrigin;
if ( dir * p->plane.Normal() > 0.0f ) {
return;
}
}
if ( cm_drawNormals.GetBool() ) {
center = vec3_origin;
for ( i = 0; i < p->numEdges; i++ ) {
edgeNum = p->edges[i];
edge = model->edges + abs(edgeNum);
center += model->vertices[edge->vertexNum[edgeNum < 0]].p;
}
center *= (1.0f / p->numEdges);
if ( axis.IsRotated() ) {
center = center * axis + origin;
end = center + 5 * (axis * p->plane.Normal());
} else {
center += origin;
end = center + 5 * p->plane.Normal();
}
common->RW()->DebugArrow( colorMagenta, center, end, 1 );
}
if ( cm_drawFilled.GetBool() ) {
idFixedWinding winding;
for ( i = p->numEdges - 1; i >= 0; i-- ) {
edgeNum = p->edges[i];
edge = model->edges + abs(edgeNum);
winding += origin + model->vertices[edge->vertexNum[INT32_SIGNBITSET(edgeNum)]].p * axis;
}
common->RW()->DebugPolygon( cm_color, winding );
} else {
for ( i = 0; i < p->numEdges; i++ ) {
edgeNum = p->edges[i];
edge = model->edges + abs(edgeNum);
if ( edge->checkcount == checkCount ) {
continue;
}
edge->checkcount = checkCount;
DrawEdge( model, edgeNum, origin, axis );
}
}
}
/*
================
idCollisionModelManagerLocal::DrawNodePolygons
================
*/
void idCollisionModelManagerLocal::DrawNodePolygons( cm_model_t *model, cm_node_t *node,
const idVec3 &origin, const idMat3 &axis,
const idVec3 &viewOrigin, const float radius ) {
int i;
cm_polygon_t *p;
cm_polygonRef_t *pref;
while (1) {
for ( pref = node->polygons; pref; pref = pref->next ) {
p = pref->p;
if ( radius ) {
// polygon bounds should overlap with trace bounds
for ( i = 0; i < 3; i++ ) {
if ( p->bounds[0][i] > viewOrigin[i] + radius ) {
break;
}
if ( p->bounds[1][i] < viewOrigin[i] - radius ) {
break;
}
}
if ( i < 3 ) {
continue;
}
}
if ( p->checkcount == checkCount ) {
continue;
}
if ( !( p->contents & cm_contentsFlagByIndex[cm_drawMask.GetInteger()] ) ) {
continue;
}
DrawPolygon( model, p, origin, axis, viewOrigin );
p->checkcount = checkCount;
}
if ( node->planeType == -1 ) {
break;
}
if ( radius && viewOrigin[node->planeType] > node->planeDist + radius ) {
node = node->children[0];
} else if ( radius && viewOrigin[node->planeType] < node->planeDist - radius ) {
node = node->children[1];
} else {
DrawNodePolygons( model, node->children[1], origin, axis, viewOrigin, radius );
node = node->children[0];
}
}
}
/*
================
idCollisionModelManagerLocal::DrawModel
================
*/
void idCollisionModelManagerLocal::DrawModel( cmHandle_t handle, const idVec3 &modelOrigin, const idMat3 &modelAxis,
const idVec3 &viewOrigin, const float radius ) {
cm_model_t *model;
idVec3 viewPos;
if ( handle < 0 && handle >= numModels ) {
return;
}
if ( cm_drawColor.IsModified() ) {
sscanf( cm_drawColor.GetString(), "%f %f %f %f", &cm_color.x, &cm_color.y, &cm_color.z, &cm_color.w );
cm_drawColor.ClearModified();
}
model = models[ handle ];
viewPos = (viewOrigin - modelOrigin) * modelAxis.Transpose();
checkCount++;
DrawNodePolygons( model, model->node, modelOrigin, modelAxis, viewPos, radius );
}
/*
===============================================================================
Speed test code
===============================================================================
*/
static idCVar cm_testCollision( "cm_testCollision", "0", CVAR_GAME | CVAR_BOOL, "" );
static idCVar cm_testRotation( "cm_testRotation", "1", CVAR_GAME | CVAR_BOOL, "" );
static idCVar cm_testModel( "cm_testModel", "0", CVAR_GAME | CVAR_INTEGER, "" );
static idCVar cm_testTimes( "cm_testTimes", "1000", CVAR_GAME | CVAR_INTEGER, "" );
static idCVar cm_testRandomMany( "cm_testRandomMany", "0", CVAR_GAME | CVAR_BOOL, "" );
static idCVar cm_testOrigin( "cm_testOrigin", "0 0 0", CVAR_GAME, "" );
static idCVar cm_testReset( "cm_testReset", "0", CVAR_GAME | CVAR_BOOL, "" );
static idCVar cm_testBox( "cm_testBox", "-16 -16 0 16 16 64", CVAR_GAME, "" );
static idCVar cm_testBoxRotation( "cm_testBoxRotation", "0 0 0", CVAR_GAME, "" );
static idCVar cm_testWalk( "cm_testWalk", "1", CVAR_GAME | CVAR_BOOL, "" );
static idCVar cm_testLength( "cm_testLength", "1024", CVAR_GAME | CVAR_FLOAT, "" );
static idCVar cm_testRadius( "cm_testRadius", "64", CVAR_GAME | CVAR_FLOAT, "" );
static idCVar cm_testAngle( "cm_testAngle", "60", CVAR_GAME | CVAR_FLOAT, "" );
static int total_translation;
static int min_translation = 999999;
static int max_translation = -999999;
static int num_translation = 0;
static int total_rotation;
static int min_rotation = 999999;
static int max_rotation = -999999;
static int num_rotation = 0;
static idVec3 start;
static idVec3 *testend;
#include "../sys/sys_public.h"
void idCollisionModelManagerLocal::DebugOutput( const idVec3 &origin ) {
int i, k, t;
char buf[128];
idVec3 end;
idAngles boxAngles;
idMat3 modelAxis, boxAxis;
idBounds bounds;
trace_t trace;
if ( !cm_testCollision.GetBool() ) {
return;
}
testend = (idVec3 *) Mem_Alloc( cm_testTimes.GetInteger() * sizeof(idVec3), TAG_COLLISION );
if ( cm_testReset.GetBool() || ( cm_testWalk.GetBool() && !start.Compare( start ) ) ) {
total_translation = total_rotation = 0;
min_translation = min_rotation = 999999;
max_translation = max_rotation = -999999;
num_translation = num_rotation = 0;
cm_testReset.SetBool( false );
}
if ( cm_testWalk.GetBool() ) {
start = origin;
cm_testOrigin.SetString( va( "%1.2f %1.2f %1.2f", start[0], start[1], start[2] ) );
} else {
sscanf( cm_testOrigin.GetString(), "%f %f %f", &start[0], &start[1], &start[2] );
}
sscanf( cm_testBox.GetString(), "%f %f %f %f %f %f", &bounds[0][0], &bounds[0][1], &bounds[0][2],
&bounds[1][0], &bounds[1][1], &bounds[1][2] );
sscanf( cm_testBoxRotation.GetString(), "%f %f %f", &boxAngles[0], &boxAngles[1], &boxAngles[2] );
boxAxis = boxAngles.ToMat3();
modelAxis.Identity();
idTraceModel itm( bounds );
idRandom random( 0 );
idTimer timer;
if ( cm_testRandomMany.GetBool() ) {
// if many traces in one random direction
for ( i = 0; i < 3; i++ ) {
testend[0][i] = start[i] + random.CRandomFloat() * cm_testLength.GetFloat();
}
for ( k = 1; k < cm_testTimes.GetInteger(); k++ ) {
testend[k] = testend[0];
}
} else {
// many traces each in a different random direction
for ( k = 0; k < cm_testTimes.GetInteger(); k++ ) {
for ( i = 0; i < 3; i++ ) {
testend[k][i] = start[i] + random.CRandomFloat() * cm_testLength.GetFloat();
}
}
}
// translational collision detection
timer.Clear();
timer.Start();
for ( i = 0; i < cm_testTimes.GetInteger(); i++ ) {
Translation( &trace, start, testend[i], &itm, boxAxis, CONTENTS_SOLID|CONTENTS_PLAYERCLIP, cm_testModel.GetInteger(), vec3_origin, modelAxis );
}
timer.Stop();
t = timer.Milliseconds();
if ( t < min_translation ) min_translation = t;
if ( t > max_translation ) max_translation = t;
num_translation++;
total_translation += t;
if ( cm_testTimes.GetInteger() > 9999 ) {
sprintf( buf, "%3dK", (int ) ( cm_testTimes.GetInteger() / 1000 ) );
} else {
sprintf( buf, "%4d", cm_testTimes.GetInteger() );
}
common->Printf("%s translations: %4d milliseconds, (min = %d, max = %d, av = %1.1f)\n", buf, t, min_translation, max_translation, (float) total_translation / num_translation );
if ( cm_testRandomMany.GetBool() ) {
// if many traces in one random direction
for ( i = 0; i < 3; i++ ) {
testend[0][i] = start[i] + random.CRandomFloat() * cm_testRadius.GetFloat();
}
for ( k = 1; k < cm_testTimes.GetInteger(); k++ ) {
testend[k] = testend[0];
}
} else {
// many traces each in a different random direction
for ( k = 0; k < cm_testTimes.GetInteger(); k++ ) {
for ( i = 0; i < 3; i++ ) {
testend[k][i] = start[i] + random.CRandomFloat() * cm_testRadius.GetFloat();
}
}
}
if ( cm_testRotation.GetBool() ) {
// rotational collision detection
idVec3 vec( random.CRandomFloat(), random.CRandomFloat(), random.RandomFloat() );
vec.Normalize();
idRotation rotation( vec3_origin, vec, cm_testAngle.GetFloat() );
timer.Clear();
timer.Start();
for ( i = 0; i < cm_testTimes.GetInteger(); i++ ) {
rotation.SetOrigin( testend[i] );
Rotation( &trace, start, rotation, &itm, boxAxis, CONTENTS_SOLID|CONTENTS_PLAYERCLIP, cm_testModel.GetInteger(), vec3_origin, modelAxis );
}
timer.Stop();
t = timer.Milliseconds();
if ( t < min_rotation ) min_rotation = t;
if ( t > max_rotation ) max_rotation = t;
num_rotation++;
total_rotation += t;
if ( cm_testTimes.GetInteger() > 9999 ) {
sprintf( buf, "%3dK", (int ) ( cm_testTimes.GetInteger() / 1000 ) );
} else {
sprintf( buf, "%4d", cm_testTimes.GetInteger() );
}
common->Printf("%s rotation: %4d milliseconds, (min = %d, max = %d, av = %1.1f)\n", buf, t, min_rotation, max_rotation, (float) total_rotation / num_rotation );
}
Mem_Free( testend );
testend = NULL;
}

View File

@@ -0,0 +1,671 @@
/*
===========================================================================
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.
===========================================================================
*/
/*
===============================================================================
Trace model vs. polygonal model collision detection.
===============================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "CollisionModel_local.h"
#define CM_FILE_EXT "cm"
#define CM_BINARYFILE_EXT "bcm"
#define CM_FILEID "CM"
#define CM_FILEVERSION "1.00"
/*
===============================================================================
Writing of collision model file
===============================================================================
*/
void CM_GetNodeBounds( idBounds *bounds, cm_node_t *node );
int CM_GetNodeContents( cm_node_t *node );
/*
================
idCollisionModelManagerLocal::WriteNodes
================
*/
void idCollisionModelManagerLocal::WriteNodes( idFile *fp, cm_node_t *node ) {
fp->WriteFloatString( "\t( %d %f )\n", node->planeType, node->planeDist );
if ( node->planeType != -1 ) {
WriteNodes( fp, node->children[0] );
WriteNodes( fp, node->children[1] );
}
}
/*
================
idCollisionModelManagerLocal::CountPolygonMemory
================
*/
int idCollisionModelManagerLocal::CountPolygonMemory( cm_node_t *node ) const {
cm_polygonRef_t *pref;
cm_polygon_t *p;
int memory;
memory = 0;
for ( pref = node->polygons; pref; pref = pref->next ) {
p = pref->p;
if ( p->checkcount == checkCount ) {
continue;
}
p->checkcount = checkCount;
memory += sizeof( cm_polygon_t ) + ( p->numEdges - 1 ) * sizeof( p->edges[0] );
}
if ( node->planeType != -1 ) {
memory += CountPolygonMemory( node->children[0] );
memory += CountPolygonMemory( node->children[1] );
}
return memory;
}
/*
================
idCollisionModelManagerLocal::WritePolygons
================
*/
void idCollisionModelManagerLocal::WritePolygons( idFile *fp, cm_node_t *node ) {
cm_polygonRef_t *pref;
cm_polygon_t *p;
int i;
for ( pref = node->polygons; pref; pref = pref->next ) {
p = pref->p;
if ( p->checkcount == checkCount ) {
continue;
}
p->checkcount = checkCount;
fp->WriteFloatString( "\t%d (", p->numEdges );
for ( i = 0; i < p->numEdges; i++ ) {
fp->WriteFloatString( " %d", p->edges[i] );
}
fp->WriteFloatString( " ) ( %f %f %f ) %f", p->plane.Normal()[0], p->plane.Normal()[1], p->plane.Normal()[2], p->plane.Dist() );
fp->WriteFloatString( " ( %f %f %f )", p->bounds[0][0], p->bounds[0][1], p->bounds[0][2] );
fp->WriteFloatString( " ( %f %f %f )", p->bounds[1][0], p->bounds[1][1], p->bounds[1][2] );
fp->WriteFloatString( " \"%s\"\n", p->material->GetName() );
}
if ( node->planeType != -1 ) {
WritePolygons( fp, node->children[0] );
WritePolygons( fp, node->children[1] );
}
}
/*
================
idCollisionModelManagerLocal::CountBrushMemory
================
*/
int idCollisionModelManagerLocal::CountBrushMemory( cm_node_t *node ) const {
cm_brushRef_t *bref;
cm_brush_t *b;
int memory;
memory = 0;
for ( bref = node->brushes; bref; bref = bref->next ) {
b = bref->b;
if ( b->checkcount == checkCount ) {
continue;
}
b->checkcount = checkCount;
memory += sizeof( cm_brush_t ) + ( b->numPlanes - 1 ) * sizeof( b->planes[0] );
}
if ( node->planeType != -1 ) {
memory += CountBrushMemory( node->children[0] );
memory += CountBrushMemory( node->children[1] );
}
return memory;
}
/*
================
idCollisionModelManagerLocal::WriteBrushes
================
*/
void idCollisionModelManagerLocal::WriteBrushes( idFile *fp, cm_node_t *node ) {
cm_brushRef_t *bref;
cm_brush_t *b;
int i;
for ( bref = node->brushes; bref; bref = bref->next ) {
b = bref->b;
if ( b->checkcount == checkCount ) {
continue;
}
b->checkcount = checkCount;
fp->WriteFloatString( "\t%d {\n", b->numPlanes );
for ( i = 0; i < b->numPlanes; i++ ) {
fp->WriteFloatString( "\t\t( %f %f %f ) %f\n", b->planes[i].Normal()[0], b->planes[i].Normal()[1], b->planes[i].Normal()[2], b->planes[i].Dist() );
}
fp->WriteFloatString( "\t} ( %f %f %f )", b->bounds[0][0], b->bounds[0][1], b->bounds[0][2] );
fp->WriteFloatString( " ( %f %f %f ) \"%s\"\n", b->bounds[1][0], b->bounds[1][1], b->bounds[1][2], StringFromContents( b->contents ) );
}
if ( node->planeType != -1 ) {
WriteBrushes( fp, node->children[0] );
WriteBrushes( fp, node->children[1] );
}
}
/*
================
idCollisionModelManagerLocal::WriteCollisionModel
================
*/
void idCollisionModelManagerLocal::WriteCollisionModel( idFile *fp, cm_model_t *model ) {
int i, polygonMemory, brushMemory;
fp->WriteFloatString( "collisionModel \"%s\" {\n", model->name.c_str() );
// vertices
fp->WriteFloatString( "\tvertices { /* numVertices = */ %d\n", model->numVertices );
for ( i = 0; i < model->numVertices; i++ ) {
fp->WriteFloatString( "\t/* %d */ ( %f %f %f )\n", i, model->vertices[i].p[0], model->vertices[i].p[1], model->vertices[i].p[2] );
}
fp->WriteFloatString( "\t}\n" );
// edges
fp->WriteFloatString( "\tedges { /* numEdges = */ %d\n", model->numEdges );
for ( i = 0; i < model->numEdges; i++ ) {
fp->WriteFloatString( "\t/* %d */ ( %d %d ) %d %d\n", i, model->edges[i].vertexNum[0], model->edges[i].vertexNum[1], model->edges[i].internal, model->edges[i].numUsers );
}
fp->WriteFloatString( "\t}\n" );
// nodes
fp->WriteFloatString( "\tnodes {\n" );
WriteNodes( fp, model->node );
fp->WriteFloatString( "\t}\n" );
// polygons
checkCount++;
polygonMemory = CountPolygonMemory( model->node );
fp->WriteFloatString( "\tpolygons /* polygonMemory = */ %d {\n", polygonMemory );
checkCount++;
WritePolygons( fp, model->node );
fp->WriteFloatString( "\t}\n" );
// brushes
checkCount++;
brushMemory = CountBrushMemory( model->node );
fp->WriteFloatString( "\tbrushes /* brushMemory = */ %d {\n", brushMemory );
checkCount++;
WriteBrushes( fp, model->node );
fp->WriteFloatString( "\t}\n" );
// closing brace
fp->WriteFloatString( "}\n" );
}
/*
================
idCollisionModelManagerLocal::WriteCollisionModelsToFile
================
*/
void idCollisionModelManagerLocal::WriteCollisionModelsToFile( const char *filename, int firstModel, int lastModel, unsigned int mapFileCRC ) {
int i;
idFile *fp;
idStr name;
name = filename;
name.SetFileExtension( CM_FILE_EXT );
common->Printf( "writing %s\n", name.c_str() );
fp = fileSystem->OpenFileWrite( name, "fs_basepath" );
if ( !fp ) {
common->Warning( "idCollisionModelManagerLocal::WriteCollisionModelsToFile: Error opening file %s\n", name.c_str() );
return;
}
// write file id and version
fp->WriteFloatString( "%s \"%s\"\n\n", CM_FILEID, CM_FILEVERSION );
// write the map file crc
fp->WriteFloatString( "%u\n\n", mapFileCRC );
// write the collision models
for ( i = firstModel; i < lastModel; i++ ) {
WriteCollisionModel( fp, models[ i ] );
}
fileSystem->CloseFile( fp );
}
/*
================
idCollisionModelManagerLocal::WriteCollisionModelForMapEntity
================
*/
bool idCollisionModelManagerLocal::WriteCollisionModelForMapEntity( const idMapEntity *mapEnt, const char *filename, const bool testTraceModel ) {
idFile *fp;
idStr name;
cm_model_t *model;
SetupHash();
model = CollisionModelForMapEntity( mapEnt );
model->name = filename;
name = filename;
name.SetFileExtension( CM_FILE_EXT );
common->Printf( "writing %s\n", name.c_str() );
fp = fileSystem->OpenFileWrite( name, "fs_basepath" );
if ( !fp ) {
common->Printf( "idCollisionModelManagerLocal::WriteCollisionModelForMapEntity: Error opening file %s\n", name.c_str() );
FreeModel( model );
return false;
}
// write file id and version
fp->WriteFloatString( "%s \"%s\"\n\n", CM_FILEID, CM_FILEVERSION );
// write the map file crc
fp->WriteFloatString( "%u\n\n", 0 );
// write the collision model
WriteCollisionModel( fp, model );
fileSystem->CloseFile( fp );
if ( testTraceModel ) {
idTraceModel trm;
TrmFromModel( model, trm );
}
FreeModel( model );
return true;
}
/*
===============================================================================
Loading of collision model file
===============================================================================
*/
/*
================
idCollisionModelManagerLocal::ParseVertices
================
*/
void idCollisionModelManagerLocal::ParseVertices( idLexer *src, cm_model_t *model ) {
int i;
src->ExpectTokenString( "{" );
model->numVertices = src->ParseInt();
model->maxVertices = model->numVertices;
model->vertices = (cm_vertex_t *) Mem_ClearedAlloc( model->maxVertices * sizeof( cm_vertex_t ), TAG_COLLISION );
for ( i = 0; i < model->numVertices; i++ ) {
src->Parse1DMatrix( 3, model->vertices[i].p.ToFloatPtr() );
model->vertices[i].side = 0;
model->vertices[i].sideSet = 0;
model->vertices[i].checkcount = 0;
}
src->ExpectTokenString( "}" );
}
/*
================
idCollisionModelManagerLocal::ParseEdges
================
*/
void idCollisionModelManagerLocal::ParseEdges( idLexer *src, cm_model_t *model ) {
int i;
src->ExpectTokenString( "{" );
model->numEdges = src->ParseInt();
model->maxEdges = model->numEdges;
model->edges = (cm_edge_t *) Mem_ClearedAlloc( model->maxEdges * sizeof( cm_edge_t ), TAG_COLLISION );
for ( i = 0; i < model->numEdges; i++ ) {
src->ExpectTokenString( "(" );
model->edges[i].vertexNum[0] = src->ParseInt();
model->edges[i].vertexNum[1] = src->ParseInt();
src->ExpectTokenString( ")" );
model->edges[i].side = 0;
model->edges[i].sideSet = 0;
model->edges[i].internal = src->ParseInt();
model->edges[i].numUsers = src->ParseInt();
model->edges[i].normal = vec3_origin;
model->edges[i].checkcount = 0;
model->numInternalEdges += model->edges[i].internal;
}
src->ExpectTokenString( "}" );
}
/*
================
idCollisionModelManagerLocal::ParseNodes
================
*/
cm_node_t *idCollisionModelManagerLocal::ParseNodes( idLexer *src, cm_model_t *model, cm_node_t *parent ) {
cm_node_t *node;
model->numNodes++;
node = AllocNode( model, model->numNodes < NODE_BLOCK_SIZE_SMALL ? NODE_BLOCK_SIZE_SMALL : NODE_BLOCK_SIZE_LARGE );
node->brushes = NULL;
node->polygons = NULL;
node->parent = parent;
src->ExpectTokenString( "(" );
node->planeType = src->ParseInt();
node->planeDist = src->ParseFloat();
src->ExpectTokenString( ")" );
if ( node->planeType != -1 ) {
node->children[0] = ParseNodes( src, model, node );
node->children[1] = ParseNodes( src, model, node );
}
return node;
}
/*
================
idCollisionModelManagerLocal::ParsePolygons
================
*/
void idCollisionModelManagerLocal::ParsePolygons( idLexer *src, cm_model_t *model ) {
cm_polygon_t *p;
int i, numEdges;
idVec3 normal;
idToken token;
if ( src->CheckTokenType( TT_NUMBER, 0, &token ) ) {
model->polygonBlock = (cm_polygonBlock_t *) Mem_ClearedAlloc( sizeof( cm_polygonBlock_t ) + token.GetIntValue(), TAG_COLLISION );
model->polygonBlock->bytesRemaining = token.GetIntValue();
model->polygonBlock->next = ( (byte *) model->polygonBlock ) + sizeof( cm_polygonBlock_t );
}
src->ExpectTokenString( "{" );
while ( !src->CheckTokenString( "}" ) ) {
// parse polygon
numEdges = src->ParseInt();
p = AllocPolygon( model, numEdges );
p->numEdges = numEdges;
src->ExpectTokenString( "(" );
for ( i = 0; i < p->numEdges; i++ ) {
p->edges[i] = src->ParseInt();
}
src->ExpectTokenString( ")" );
src->Parse1DMatrix( 3, normal.ToFloatPtr() );
p->plane.SetNormal( normal );
p->plane.SetDist( src->ParseFloat() );
src->Parse1DMatrix( 3, p->bounds[0].ToFloatPtr() );
src->Parse1DMatrix( 3, p->bounds[1].ToFloatPtr() );
src->ExpectTokenType( TT_STRING, 0, &token );
// get material
p->material = declManager->FindMaterial( token );
p->contents = p->material->GetContentFlags();
p->checkcount = 0;
// filter polygon into tree
R_FilterPolygonIntoTree( model, model->node, NULL, p );
}
}
/*
================
idCollisionModelManagerLocal::ParseBrushes
================
*/
void idCollisionModelManagerLocal::ParseBrushes( idLexer *src, cm_model_t *model ) {
cm_brush_t *b;
int i, numPlanes;
idVec3 normal;
idToken token;
if ( src->CheckTokenType( TT_NUMBER, 0, &token ) ) {
model->brushBlock = (cm_brushBlock_t *) Mem_ClearedAlloc( sizeof( cm_brushBlock_t ) + token.GetIntValue(), TAG_COLLISION );
model->brushBlock->bytesRemaining = token.GetIntValue();
model->brushBlock->next = ( (byte *) model->brushBlock ) + sizeof( cm_brushBlock_t );
}
src->ExpectTokenString( "{" );
while ( !src->CheckTokenString( "}" ) ) {
// parse brush
numPlanes = src->ParseInt();
b = AllocBrush( model, numPlanes );
b->numPlanes = numPlanes;
src->ExpectTokenString( "{" );
for ( i = 0; i < b->numPlanes; i++ ) {
src->Parse1DMatrix( 3, normal.ToFloatPtr() );
b->planes[i].SetNormal( normal );
b->planes[i].SetDist( src->ParseFloat() );
}
src->ExpectTokenString( "}" );
src->Parse1DMatrix( 3, b->bounds[0].ToFloatPtr() );
src->Parse1DMatrix( 3, b->bounds[1].ToFloatPtr() );
src->ReadToken( &token );
if ( token.type == TT_NUMBER ) {
b->contents = token.GetIntValue(); // old .cm files use a single integer
} else {
b->contents = ContentsFromString( token );
}
b->checkcount = 0;
b->primitiveNum = 0;
b->material = NULL;
// filter brush into tree
R_FilterBrushIntoTree( model, model->node, NULL, b );
}
}
/*
================
idCollisionModelManagerLocal::ParseCollisionModel
================
*/
cm_model_t * idCollisionModelManagerLocal::ParseCollisionModel( idLexer *src ) {
cm_model_t *model;
idToken token;
if ( numModels >= MAX_SUBMODELS ) {
common->Error( "LoadModel: no free slots" );
return NULL;
}
model = AllocModel();
models[numModels ] = model;
numModels++;
// parse the file
src->ExpectTokenType( TT_STRING, 0, &token );
model->name = token;
src->ExpectTokenString( "{" );
while ( !src->CheckTokenString( "}" ) ) {
src->ReadToken( &token );
if ( token == "vertices" ) {
ParseVertices( src, model );
continue;
}
if ( token == "edges" ) {
ParseEdges( src, model );
continue;
}
if ( token == "nodes" ) {
src->ExpectTokenString( "{" );
model->node = ParseNodes( src, model, NULL );
src->ExpectTokenString( "}" );
continue;
}
if ( token == "polygons" ) {
ParsePolygons( src, model );
continue;
}
if ( token == "brushes" ) {
ParseBrushes( src, model );
continue;
}
src->Error( "ParseCollisionModel: bad token \"%s\"", token.c_str() );
}
// calculate edge normals
checkCount++;
CalculateEdgeNormals( model, model->node );
// get model bounds from brush and polygon bounds
CM_GetNodeBounds( &model->bounds, model->node );
// get model contents
model->contents = CM_GetNodeContents( model->node );
// total memory used by this model
model->usedMemory = model->numVertices * sizeof(cm_vertex_t) +
model->numEdges * sizeof(cm_edge_t) +
model->polygonMemory +
model->brushMemory +
model->numNodes * sizeof(cm_node_t) +
model->numPolygonRefs * sizeof(cm_polygonRef_t) +
model->numBrushRefs * sizeof(cm_brushRef_t);
return model;
}
/*
================
idCollisionModelManagerLocal::LoadCollisionModelFile
================
*/
bool idCollisionModelManagerLocal::LoadCollisionModelFile( const char *name, unsigned int mapFileCRC ) {
idToken token;
idLexer *src;
unsigned int crc;
// load it
idStrStatic< MAX_OSPATH > fileName = name;
// check for generated file
idStrStatic< MAX_OSPATH > generatedFileName = fileName;
generatedFileName.Insert( "generated/", 0 );
generatedFileName.SetFileExtension( CM_BINARYFILE_EXT );
// if we are reloading the same map, check the timestamp
// and try to skip all the work
ID_TIME_T currentTimeStamp = fileSystem->GetTimestamp( fileName );
// see if we have a generated version of this
bool loaded = false;
idFileLocal file( fileSystem->OpenFileReadMemory( generatedFileName ) );
if ( file != NULL ) {
int numEntries = 0;
file->ReadBig( numEntries );
file->ReadString( mapName );
file->ReadBig( crc );
idStrStatic< 32 > fileID;
idStrStatic< 32 > fileVersion;
file->ReadString( fileID );
file->ReadString( fileVersion );
if ( fileID == CM_FILEID && fileVersion == CM_FILEVERSION && crc == mapFileCRC && numEntries > 0 ) {
for ( int i = 0; i < numEntries; i++ ) {
cm_model_t *model = LoadBinaryModelFromFile( file, currentTimeStamp );
models[ numModels ] = model;
numModels++;
}
loaded = true;
}
}
if ( !loaded ) {
fileName.SetFileExtension( CM_FILE_EXT );
src = new (TAG_COLLISION) idLexer( fileName );
src->SetFlags( LEXFL_NOSTRINGCONCAT | LEXFL_NODOLLARPRECOMPILE );
if ( !src->IsLoaded() ) {
delete src;
return false;
}
int numEntries = 0;
idFileLocal outputFile( fileSystem->OpenFileWrite( generatedFileName, "fs_basepath" ) );
if ( outputFile != NULL ) {
outputFile->WriteBig( numEntries );
outputFile->WriteString( mapName );
outputFile->WriteBig( mapFileCRC );
outputFile->WriteString( CM_FILEID );
outputFile->WriteString( CM_FILEVERSION );
}
if ( !src->ExpectTokenString( CM_FILEID ) ) {
common->Warning( "%s is not an CM file.", fileName.c_str() );
delete src;
return false;
}
if ( !src->ReadToken( &token ) || token != CM_FILEVERSION ) {
common->Warning( "%s has version %s instead of %s", fileName.c_str(), token.c_str(), CM_FILEVERSION );
delete src;
return false;
}
if ( !src->ExpectTokenType( TT_NUMBER, TT_INTEGER, &token ) ) {
common->Warning( "%s has no map file CRC", fileName.c_str() );
delete src;
return false;
}
crc = token.GetUnsignedLongValue();
if ( mapFileCRC && crc != mapFileCRC ) {
common->Printf( "%s is out of date\n", fileName.c_str() );
delete src;
return false;
}
// parse the file
while ( 1 ) {
if ( !src->ReadToken( &token ) ) {
break;
}
if ( token == "collisionModel" ) {
cm_model_t *model = ParseCollisionModel( src );
if ( model == NULL ) {
delete src;
return false;
}
if ( outputFile != NULL ) {
WriteBinaryModelToFile( model, outputFile, currentTimeStamp );
numEntries++;
}
continue;
}
src->Error( "idCollisionModelManagerLocal::LoadCollisionModelFile: bad token \"%s\"", token.c_str() );
}
delete src;
if ( outputFile != NULL ) {
outputFile->Seek( 0, FS_SEEK_SET );
outputFile->WriteBig( numEntries );
}
}
return true;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,539 @@
/*
===========================================================================
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.
===========================================================================
*/
/*
===============================================================================
Trace model vs. polygonal model collision detection.
===============================================================================
*/
#include "CollisionModel.h"
#define MIN_NODE_SIZE 64.0f
#define MAX_NODE_POLYGONS 128
#define CM_MAX_POLYGON_EDGES 64
#define CIRCLE_APPROXIMATION_LENGTH 64.0f
#define MAX_SUBMODELS 2048
#define TRACE_MODEL_HANDLE MAX_SUBMODELS
#define VERTEX_HASH_BOXSIZE (1<<6) // must be power of 2
#define VERTEX_HASH_SIZE (VERTEX_HASH_BOXSIZE*VERTEX_HASH_BOXSIZE)
#define EDGE_HASH_SIZE (1<<14)
#define NODE_BLOCK_SIZE_SMALL 8
#define NODE_BLOCK_SIZE_LARGE 256
#define REFERENCE_BLOCK_SIZE_SMALL 8
#define REFERENCE_BLOCK_SIZE_LARGE 256
#define MAX_WINDING_LIST 128 // quite a few are generated at times
#define INTEGRAL_EPSILON 0.01f
#define VERTEX_EPSILON 0.1f
#define CHOP_EPSILON 0.1f
typedef struct cm_windingList_s {
int numWindings; // number of windings
idFixedWinding w[MAX_WINDING_LIST]; // windings
idVec3 normal; // normal for all windings
idBounds bounds; // bounds of all windings in list
idVec3 origin; // origin for radius
float radius; // radius relative to origin for all windings
int contents; // winding surface contents
int primitiveNum; // number of primitive the windings came from
} cm_windingList_t;
/*
===============================================================================
Collision model
===============================================================================
*/
typedef struct cm_vertex_s {
idVec3 p; // vertex point
int checkcount; // for multi-check avoidance
unsigned long side; // each bit tells at which side this vertex passes one of the trace model edges
unsigned long sideSet; // each bit tells if sidedness for the trace model edge has been calculated yet
} cm_vertex_t;
typedef struct cm_edge_s {
int checkcount; // for multi-check avoidance
unsigned short internal; // a trace model can never collide with internal edges
unsigned short numUsers; // number of polygons using this edge
unsigned long side; // each bit tells at which side of this edge one of the trace model vertices passes
unsigned long sideSet; // each bit tells if sidedness for the trace model vertex has been calculated yet
int vertexNum[2]; // start and end point of edge
idVec3 normal; // edge normal
} cm_edge_t;
typedef struct cm_polygonBlock_s {
int bytesRemaining;
byte * next;
} cm_polygonBlock_t;
typedef struct cm_polygon_s {
idBounds bounds; // polygon bounds
int checkcount; // for multi-check avoidance
int contents; // contents behind polygon
const idMaterial * material; // material
idPlane plane; // polygon plane
int numEdges; // number of edges
int edges[1]; // variable sized, indexes into cm_edge_t list
} cm_polygon_t;
typedef struct cm_polygonRef_s {
cm_polygon_t * p; // pointer to polygon
struct cm_polygonRef_s *next; // next polygon in chain
} cm_polygonRef_t;
typedef struct cm_polygonRefBlock_s {
cm_polygonRef_t * nextRef; // next polygon reference in block
struct cm_polygonRefBlock_s *next; // next block with polygon references
} cm_polygonRefBlock_t;
typedef struct cm_brushBlock_s {
int bytesRemaining;
byte * next;
} cm_brushBlock_t;
typedef struct cm_brush_s {
cm_brush_s() {
checkcount = 0;
contents = 0;
material = NULL;
primitiveNum = 0;
numPlanes = 0;
}
int checkcount; // for multi-check avoidance
idBounds bounds; // brush bounds
int contents; // contents of brush
const idMaterial * material; // material
int primitiveNum; // number of brush primitive
int numPlanes; // number of bounding planes
idPlane planes[1]; // variable sized
} cm_brush_t;
typedef struct cm_brushRef_s {
cm_brush_t * b; // pointer to brush
struct cm_brushRef_s * next; // next brush in chain
} cm_brushRef_t;
typedef struct cm_brushRefBlock_s {
cm_brushRef_t * nextRef; // next brush reference in block
struct cm_brushRefBlock_s *next; // next block with brush references
} cm_brushRefBlock_t;
typedef struct cm_node_s {
int planeType; // node axial plane type
float planeDist; // node plane distance
cm_polygonRef_t * polygons; // polygons in node
cm_brushRef_t * brushes; // brushes in node
struct cm_node_s * parent; // parent of this node
struct cm_node_s * children[2]; // node children
} cm_node_t;
typedef struct cm_nodeBlock_s {
cm_node_t * nextNode; // next node in block
struct cm_nodeBlock_s *next; // next block with nodes
} cm_nodeBlock_t;
typedef struct cm_model_s {
idStr name; // model name
idBounds bounds; // model bounds
int contents; // all contents of the model ored together
bool isConvex; // set if model is convex
// model geometry
int maxVertices; // size of vertex array
int numVertices; // number of vertices
cm_vertex_t * vertices; // array with all vertices used by the model
int maxEdges; // size of edge array
int numEdges; // number of edges
cm_edge_t * edges; // array with all edges used by the model
cm_node_t * node; // first node of spatial subdivision
// blocks with allocated memory
cm_nodeBlock_t * nodeBlocks; // list with blocks of nodes
cm_polygonRefBlock_t * polygonRefBlocks; // list with blocks of polygon references
cm_brushRefBlock_t * brushRefBlocks; // list with blocks of brush references
cm_polygonBlock_t * polygonBlock; // memory block with all polygons
cm_brushBlock_t * brushBlock; // memory block with all brushes
// statistics
int numPolygons;
int polygonMemory;
int numBrushes;
int brushMemory;
int numNodes;
int numBrushRefs;
int numPolygonRefs;
int numInternalEdges;
int numSharpEdges;
int numRemovedPolys;
int numMergedPolys;
int usedMemory;
} cm_model_t;
/*
===============================================================================
Data used during collision detection calculations
===============================================================================
*/
typedef struct cm_trmVertex_s {
int used; // true if this vertex is used for collision detection
idVec3 p; // vertex position
idVec3 endp; // end point of vertex after movement
int polygonSide; // side of polygon this vertex is on (rotational collision)
idPluecker pl; // pluecker coordinate for vertex movement
idVec3 rotationOrigin; // rotation origin for this vertex
idBounds rotationBounds; // rotation bounds for this vertex
} cm_trmVertex_t;
typedef struct cm_trmEdge_s {
int used; // true when vertex is used for collision detection
idVec3 start; // start of edge
idVec3 end; // end of edge
int vertexNum[2]; // indexes into cm_traceWork_t->vertices
idPluecker pl; // pluecker coordinate for edge
idVec3 cross; // (z,-y,x) of cross product between edge dir and movement dir
idBounds rotationBounds; // rotation bounds for this edge
idPluecker plzaxis; // pluecker coordinate for rotation about the z-axis
unsigned short bitNum; // vertex bit number
} cm_trmEdge_t;
typedef struct cm_trmPolygon_s {
int used;
idPlane plane; // polygon plane
int numEdges; // number of edges
int edges[MAX_TRACEMODEL_POLYEDGES]; // index into cm_traceWork_t->edges
idBounds rotationBounds; // rotation bounds for this polygon
} cm_trmPolygon_t;
typedef struct cm_traceWork_s {
int numVerts;
cm_trmVertex_t vertices[MAX_TRACEMODEL_VERTS]; // trm vertices
int numEdges;
cm_trmEdge_t edges[MAX_TRACEMODEL_EDGES+1]; // trm edges
int numPolys;
cm_trmPolygon_t polys[MAX_TRACEMODEL_POLYS]; // trm polygons
cm_model_t *model; // model colliding with
idVec3 start; // start of trace
idVec3 end; // end of trace
idVec3 dir; // trace direction
idBounds bounds; // bounds of full trace
idBounds size; // bounds of transformed trm relative to start
idVec3 extents; // largest of abs(size[0]) and abs(size[1]) for BSP trace
int contents; // ignore polygons that do not have any of these contents flags
trace_t trace; // collision detection result
bool rotation; // true if calculating rotational collision
bool pointTrace; // true if only tracing a point
bool positionTest; // true if not tracing but doing a position test
bool isConvex; // true if the trace model is convex
bool axisIntersectsTrm; // true if the rotation axis intersects the trace model
bool getContacts; // true if retrieving contacts
bool quickExit; // set to quickly stop the collision detection calculations
idVec3 origin; // origin of rotation in model space
idVec3 axis; // rotation axis in model space
idMat3 matrix; // rotates axis of rotation to the z-axis
float angle; // angle for rotational collision
float maxTan; // max tangent of half the positive angle used instead of fraction
float radius; // rotation radius of trm start
idRotation modelVertexRotation; // inverse rotation for model vertices
contactInfo_t *contacts; // array with contacts
int maxContacts; // max size of contact array
int numContacts; // number of contacts found
idPlane heartPlane1; // polygons should be near anough the trace heart planes
float maxDistFromHeartPlane1;
idPlane heartPlane2;
float maxDistFromHeartPlane2;
idPluecker polygonEdgePlueckerCache[CM_MAX_POLYGON_EDGES];
idPluecker polygonVertexPlueckerCache[CM_MAX_POLYGON_EDGES];
idVec3 polygonRotationOriginCache[CM_MAX_POLYGON_EDGES];
} cm_traceWork_t;
/*
===============================================================================
Collision Map
===============================================================================
*/
typedef struct cm_procNode_s {
idPlane plane;
int children[2]; // negative numbers are (-1 - areaNumber), 0 = solid
} cm_procNode_t;
class idCollisionModelManagerLocal : public idCollisionModelManager {
public:
// load collision models from a map file
void LoadMap( const idMapFile *mapFile );
// frees all the collision models
void FreeMap();
void Preload( const char *mapName );
// get clip handle for model
cmHandle_t LoadModel( const char *modelName );
// sets up a trace model for collision with other trace models
cmHandle_t SetupTrmModel( const idTraceModel &trm, const idMaterial *material );
// create trace model from a collision model, returns true if succesfull
bool TrmFromModel( const char *modelName, idTraceModel &trm );
// name of the model
const char * GetModelName( cmHandle_t model ) const;
// bounds of the model
bool GetModelBounds( cmHandle_t model, idBounds &bounds ) const;
// all contents flags of brushes and polygons ored together
bool GetModelContents( cmHandle_t model, int &contents ) const;
// get the vertex of a model
bool GetModelVertex( cmHandle_t model, int vertexNum, idVec3 &vertex ) const;
// get the edge of a model
bool GetModelEdge( cmHandle_t model, int edgeNum, idVec3 &start, idVec3 &end ) const;
// get the polygon of a model
bool GetModelPolygon( cmHandle_t model, int polygonNum, idFixedWinding &winding ) const;
// translates a trm and reports the first collision if any
void Translation( trace_t *results, const idVec3 &start, const idVec3 &end,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
// rotates a trm and reports the first collision if any
void Rotation( trace_t *results, const idVec3 &start, const idRotation &rotation,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
// returns the contents the trm is stuck in or 0 if the trm is in free space
int Contents( const idVec3 &start,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
// stores all contact points of the trm with the model, returns the number of contacts
int Contacts( contactInfo_t *contacts, const int maxContacts, const idVec3 &start, const idVec6 &dir, const float depth,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
// test collision detection
void DebugOutput( const idVec3 &origin );
// draw a model
void DrawModel( cmHandle_t model, const idVec3 &origin, const idMat3 &axis,
const idVec3 &viewOrigin, const float radius );
// print model information, use -1 handle for accumulated model info
void ModelInfo( cmHandle_t model );
// list all loaded models
void ListModels();
// write a collision model file for the map entity
bool WriteCollisionModelForMapEntity( const idMapEntity *mapEnt, const char *filename, const bool testTraceModel = true );
private: // CollisionMap_translate.cpp
int TranslateEdgeThroughEdge( idVec3 &cross, idPluecker &l1, idPluecker &l2, float *fraction );
void TranslateTrmEdgeThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmEdge_t *trmEdge );
void TranslateTrmVertexThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmVertex_t *v, int bitNum );
void TranslatePointThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmVertex_t *v );
void TranslateVertexThroughTrmPolygon( cm_traceWork_t *tw, cm_trmPolygon_t *trmpoly, cm_polygon_t *poly, cm_vertex_t *v, idVec3 &endp, idPluecker &pl );
bool TranslateTrmThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *p );
void SetupTranslationHeartPlanes( cm_traceWork_t *tw );
void SetupTrm( cm_traceWork_t *tw, const idTraceModel *trm );
private: // CollisionMap_rotate.cpp
int CollisionBetweenEdgeBounds( cm_traceWork_t *tw, const idVec3 &va, const idVec3 &vb,
const idVec3 &vc, const idVec3 &vd, float tanHalfAngle,
idVec3 &collisionPoint, idVec3 &collisionNormal );
int RotateEdgeThroughEdge( cm_traceWork_t *tw, const idPluecker &pl1,
const idVec3 &vc, const idVec3 &vd,
const float minTan, float &tanHalfAngle );
int EdgeFurthestFromEdge( cm_traceWork_t *tw, const idPluecker &pl1,
const idVec3 &vc, const idVec3 &vd,
float &tanHalfAngle, float &dir );
void RotateTrmEdgeThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmEdge_t *trmEdge );
int RotatePointThroughPlane( const cm_traceWork_t *tw, const idVec3 &point, const idPlane &plane,
const float angle, const float minTan, float &tanHalfAngle );
int PointFurthestFromPlane( const cm_traceWork_t *tw, const idVec3 &point, const idPlane &plane,
const float angle, float &tanHalfAngle, float &dir );
int RotatePointThroughEpsilonPlane( const cm_traceWork_t *tw, const idVec3 &point, const idVec3 &endPoint,
const idPlane &plane, const float angle, const idVec3 &origin,
float &tanHalfAngle, idVec3 &collisionPoint, idVec3 &endDir );
void RotateTrmVertexThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmVertex_t *v, int vertexNum);
void RotateVertexThroughTrmPolygon( cm_traceWork_t *tw, cm_trmPolygon_t *trmpoly, cm_polygon_t *poly,
cm_vertex_t *v, idVec3 &rotationOrigin );
bool RotateTrmThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *p );
void BoundsForRotation( const idVec3 &origin, const idVec3 &axis, const idVec3 &start, const idVec3 &end, idBounds &bounds );
void Rotation180( trace_t *results, const idVec3 &rorg, const idVec3 &axis,
const float startAngle, const float endAngle, const idVec3 &start,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &origin, const idMat3 &modelAxis );
private: // CollisionMap_contents.cpp
bool TestTrmVertsInBrush( cm_traceWork_t *tw, cm_brush_t *b );
bool TestTrmInPolygon( cm_traceWork_t *tw, cm_polygon_t *p );
cm_node_t * PointNode( const idVec3 &p, cm_model_t *model );
int PointContents( const idVec3 p, cmHandle_t model );
int TransformedPointContents( const idVec3 &p, cmHandle_t model, const idVec3 &origin, const idMat3 &modelAxis );
int ContentsTrm( trace_t *results, const idVec3 &start,
const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
private: // CollisionMap_trace.cpp
void TraceTrmThroughNode( cm_traceWork_t *tw, cm_node_t *node );
void TraceThroughAxialBSPTree_r( cm_traceWork_t *tw, cm_node_t *node, float p1f, float p2f, idVec3 &p1, idVec3 &p2);
void TraceThroughModel( cm_traceWork_t *tw );
void RecurseProcBSP_r( trace_t *results, int parentNodeNum, int nodeNum, float p1f, float p2f, const idVec3 &p1, const idVec3 &p2 );
private: // CollisionMap_load.cpp
void Clear();
void FreeTrmModelStructure();
// model deallocation
void RemovePolygonReferences_r( cm_node_t *node, cm_polygon_t *p );
void RemoveBrushReferences_r( cm_node_t *node, cm_brush_t *b );
void FreeNode( cm_node_t *node );
void FreePolygonReference( cm_polygonRef_t *pref );
void FreeBrushReference( cm_brushRef_t *bref );
void FreePolygon( cm_model_t *model, cm_polygon_t *poly );
void FreeBrush( cm_model_t *model, cm_brush_t *brush );
void FreeTree_r( cm_model_t *model, cm_node_t *headNode, cm_node_t *node );
void FreeModel( cm_model_t *model );
// merging polygons
void ReplacePolygons( cm_model_t *model, cm_node_t *node, cm_polygon_t *p1, cm_polygon_t *p2, cm_polygon_t *newp );
cm_polygon_t * TryMergePolygons( cm_model_t *model, cm_polygon_t *p1, cm_polygon_t *p2 );
bool MergePolygonWithTreePolygons( cm_model_t *model, cm_node_t *node, cm_polygon_t *polygon );
void MergeTreePolygons( cm_model_t *model, cm_node_t *node );
// finding internal edges
bool PointInsidePolygon( cm_model_t *model, cm_polygon_t *p, idVec3 &v );
void FindInternalEdgesOnPolygon( cm_model_t *model, cm_polygon_t *p1, cm_polygon_t *p2 );
void FindInternalPolygonEdges( cm_model_t *model, cm_node_t *node, cm_polygon_t *polygon );
void FindInternalEdges( cm_model_t *model, cm_node_t *node );
void FindContainedEdges( cm_model_t *model, cm_polygon_t *p );
// loading of proc BSP tree
void ParseProcNodes( idLexer *src );
void LoadProcBSP( const char *name );
// removal of contained polygons
int R_ChoppedAwayByProcBSP( int nodeNum, idFixedWinding *w, const idVec3 &normal, const idVec3 &origin, const float radius );
int ChoppedAwayByProcBSP( const idFixedWinding &w, const idPlane &plane, int contents );
void ChopWindingListWithBrush( cm_windingList_t *list, cm_brush_t *b );
void R_ChopWindingListWithTreeBrushes( cm_windingList_t *list, cm_node_t *node );
idFixedWinding *WindingOutsideBrushes( idFixedWinding *w, const idPlane &plane, int contents, int patch, cm_node_t *headNode );
// creation of axial BSP tree
cm_model_t * AllocModel();
cm_node_t * AllocNode( cm_model_t *model, int blockSize );
cm_polygonRef_t*AllocPolygonReference( cm_model_t *model, int blockSize );
cm_brushRef_t * AllocBrushReference( cm_model_t *model, int blockSize );
cm_polygon_t * AllocPolygon( cm_model_t *model, int numEdges );
cm_brush_t * AllocBrush( cm_model_t *model, int numPlanes );
void AddPolygonToNode( cm_model_t *model, cm_node_t *node, cm_polygon_t *p );
void AddBrushToNode( cm_model_t *model, cm_node_t *node, cm_brush_t *b );
void SetupTrmModelStructure();
void R_FilterPolygonIntoTree( cm_model_t *model, cm_node_t *node, cm_polygonRef_t *pref, cm_polygon_t *p );
void R_FilterBrushIntoTree( cm_model_t *model, cm_node_t *node, cm_brushRef_t *pref, cm_brush_t *b );
cm_node_t * R_CreateAxialBSPTree( cm_model_t *model, cm_node_t *node, const idBounds &bounds );
cm_node_t * CreateAxialBSPTree( cm_model_t *model, cm_node_t *node );
// creation of raw polygons
void SetupHash();
void ShutdownHash();
void ClearHash( idBounds &bounds );
int HashVec(const idVec3 &vec);
int GetVertex( cm_model_t *model, const idVec3 &v, int *vertexNum );
int GetEdge( cm_model_t *model, const idVec3 &v1, const idVec3 &v2, int *edgeNum, int v1num );
void CreatePolygon( cm_model_t *model, idFixedWinding *w, const idPlane &plane, const idMaterial *material, int primitiveNum );
void PolygonFromWinding( cm_model_t *model, idFixedWinding *w, const idPlane &plane, const idMaterial *material, int primitiveNum );
void CalculateEdgeNormals( cm_model_t *model, cm_node_t *node );
void CreatePatchPolygons( cm_model_t *model, idSurface_Patch &mesh, const idMaterial *material, int primitiveNum );
void ConvertPatch( cm_model_t *model, const idMapPatch *patch, int primitiveNum );
void ConvertBrushSides( cm_model_t *model, const idMapBrush *mapBrush, int primitiveNum );
void ConvertBrush( cm_model_t *model, const idMapBrush *mapBrush, int primitiveNum );
void PrintModelInfo( const cm_model_t *model );
void AccumulateModelInfo( cm_model_t *model );
void RemapEdges( cm_node_t *node, int *edgeRemap );
void OptimizeArrays( cm_model_t *model );
void FinishModel( cm_model_t *model );
void BuildModels( const idMapFile *mapFile );
cmHandle_t FindModel( const char *name );
cm_model_t * CollisionModelForMapEntity( const idMapEntity *mapEnt ); // brush/patch model from .map
cm_model_t * LoadRenderModel( const char *fileName ); // ASE/LWO models
cm_model_t * LoadBinaryModel( const char *fileName, ID_TIME_T sourceTimeStamp );
cm_model_t * LoadBinaryModelFromFile( idFile *fileIn, ID_TIME_T sourceTimeStamp );
void WriteBinaryModel( cm_model_t *model, const char *fileName, ID_TIME_T sourceTimeStamp );
void WriteBinaryModelToFile( cm_model_t *model, idFile *fileOut, ID_TIME_T sourceTimeStamp );
bool TrmFromModel_r( idTraceModel &trm, cm_node_t *node );
bool TrmFromModel( const cm_model_t *model, idTraceModel &trm );
private: // CollisionMap_files.cpp
// writing
void WriteNodes( idFile *fp, cm_node_t *node );
int CountPolygonMemory( cm_node_t *node ) const;
void WritePolygons( idFile *fp, cm_node_t *node );
int CountBrushMemory( cm_node_t *node ) const;
void WriteBrushes( idFile *fp, cm_node_t *node );
void WriteCollisionModel( idFile *fp, cm_model_t *model );
void WriteCollisionModelsToFile( const char *filename, int firstModel, int lastModel, unsigned int mapFileCRC );
// loading
cm_node_t * ParseNodes( idLexer *src, cm_model_t *model, cm_node_t *parent );
void ParseVertices( idLexer *src, cm_model_t *model );
void ParseEdges( idLexer *src, cm_model_t *model );
void ParsePolygons( idLexer *src, cm_model_t *model );
void ParseBrushes( idLexer *src, cm_model_t *model );
cm_model_t * ParseCollisionModel( idLexer *src );
bool LoadCollisionModelFile( const char *name, unsigned int mapFileCRC );
private: // CollisionMap_debug
int ContentsFromString( const char *string ) const;
const char * StringFromContents( const int contents ) const;
void DrawEdge( cm_model_t *model, int edgeNum, const idVec3 &origin, const idMat3 &axis );
void DrawPolygon( cm_model_t *model, cm_polygon_t *p, const idVec3 &origin, const idMat3 &axis,
const idVec3 &viewOrigin );
void DrawNodePolygons( cm_model_t *model, cm_node_t *node, const idVec3 &origin, const idMat3 &axis,
const idVec3 &viewOrigin, const float radius );
private: // collision map data
idStr mapName;
ID_TIME_T mapFileTime;
int loaded;
// for multi-check avoidance
int checkCount;
// models
int maxModels;
int numModels;
cm_model_t ** models;
// polygons and brush for trm model
cm_polygonRef_t*trmPolygons[MAX_TRACEMODEL_POLYS];
cm_brushRef_t * trmBrushes[1];
const idMaterial *trmMaterial;
// for data pruning
int numProcNodes;
cm_procNode_t * procNodes;
// for retrieving contact points
bool getContacts;
contactInfo_t * contacts;
int maxContacts;
int numContacts;
};
// for debugging
extern idCVar cm_debugCollision;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,257 @@
/*
===========================================================================
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.
===========================================================================
*/
/*
===============================================================================
Trace model vs. polygonal model collision detection.
===============================================================================
*/
#pragma hdrstop
#include "../idlib/precompiled.h"
#include "CollisionModel_local.h"
/*
===============================================================================
Trace through the spatial subdivision
===============================================================================
*/
/*
================
idCollisionModelManagerLocal::TraceTrmThroughNode
================
*/
void idCollisionModelManagerLocal::TraceTrmThroughNode( cm_traceWork_t *tw, cm_node_t *node ) {
cm_polygonRef_t *pref;
cm_brushRef_t *bref;
// position test
if ( tw->positionTest ) {
// if already stuck in solid
if ( tw->trace.fraction == 0.0f ) {
return;
}
// test if any of the trm vertices is inside a brush
for ( bref = node->brushes; bref; bref = bref->next ) {
if ( idCollisionModelManagerLocal::TestTrmVertsInBrush( tw, bref->b ) ) {
return;
}
}
// if just testing a point we're done
if ( tw->pointTrace ) {
return;
}
// test if the trm is stuck in any polygons
for ( pref = node->polygons; pref; pref = pref->next ) {
if ( idCollisionModelManagerLocal::TestTrmInPolygon( tw, pref->p ) ) {
return;
}
}
}
else if ( tw->rotation ) {
// rotate through all polygons in this leaf
for ( pref = node->polygons; pref; pref = pref->next ) {
if ( idCollisionModelManagerLocal::RotateTrmThroughPolygon( tw, pref->p ) ) {
return;
}
}
}
else {
// trace through all polygons in this leaf
for ( pref = node->polygons; pref; pref = pref->next ) {
if ( idCollisionModelManagerLocal::TranslateTrmThroughPolygon( tw, pref->p ) ) {
return;
}
}
}
}
/*
================
idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r
================
*/
//#define NO_SPATIAL_SUBDIVISION
void idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r( cm_traceWork_t *tw, cm_node_t *node, float p1f, float p2f, idVec3 &p1, idVec3 &p2) {
float t1, t2, offset;
float frac, frac2;
float idist;
idVec3 mid;
int side;
float midf;
if ( !node ) {
return;
}
if ( tw->quickExit ) {
return; // stop immediately
}
if ( tw->trace.fraction <= p1f ) {
return; // already hit something nearer
}
// if we need to test this node for collisions
if ( node->polygons || (tw->positionTest && node->brushes) ) {
// trace through node with collision data
idCollisionModelManagerLocal::TraceTrmThroughNode( tw, node );
}
// if already stuck in solid
if ( tw->positionTest && tw->trace.fraction == 0.0f ) {
return;
}
// if this is a leaf node
if ( node->planeType == -1 ) {
return;
}
#ifdef NO_SPATIAL_SUBDIVISION
idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r( tw, node->children[0], p1f, p2f, p1, p2 );
idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r( tw, node->children[1], p1f, p2f, p1, p2 );
return;
#endif
// distance from plane for trace start and end
t1 = p1[node->planeType] - node->planeDist;
t2 = p2[node->planeType] - node->planeDist;
// adjust the plane distance appropriately for mins/maxs
offset = tw->extents[node->planeType];
// see which sides we need to consider
if ( t1 >= offset && t2 >= offset ) {
idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r( tw, node->children[0], p1f, p2f, p1, p2 );
return;
}
if ( t1 < -offset && t2 < -offset ) {
idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r( tw, node->children[1], p1f, p2f, p1, p2 );
return;
}
if ( t1 < t2 ) {
idist = 1.0f / (t1-t2);
side = 1;
frac2 = (t1 + offset) * idist;
frac = (t1 - offset) * idist;
} else if (t1 > t2) {
idist = 1.0f / (t1-t2);
side = 0;
frac2 = (t1 - offset) * idist;
frac = (t1 + offset) * idist;
} else {
side = 0;
frac = 1.0f;
frac2 = 0.0f;
}
// move up to the node
if ( frac < 0.0f ) {
frac = 0.0f;
}
else if ( frac > 1.0f ) {
frac = 1.0f;
}
midf = p1f + (p2f - p1f)*frac;
mid[0] = p1[0] + frac*(p2[0] - p1[0]);
mid[1] = p1[1] + frac*(p2[1] - p1[1]);
mid[2] = p1[2] + frac*(p2[2] - p1[2]);
idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r( tw, node->children[side], p1f, midf, p1, mid );
// go past the node
if ( frac2 < 0.0f ) {
frac2 = 0.0f;
}
else if ( frac2 > 1.0f ) {
frac2 = 1.0f;
}
midf = p1f + (p2f - p1f)*frac2;
mid[0] = p1[0] + frac2*(p2[0] - p1[0]);
mid[1] = p1[1] + frac2*(p2[1] - p1[1]);
mid[2] = p1[2] + frac2*(p2[2] - p1[2]);
idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r( tw, node->children[side^1], midf, p2f, mid, p2 );
}
/*
================
idCollisionModelManagerLocal::TraceThroughModel
================
*/
void idCollisionModelManagerLocal::TraceThroughModel( cm_traceWork_t *tw ) {
float d;
int i, numSteps;
idVec3 start, end;
idRotation rot;
if ( !tw->rotation ) {
// trace through spatial subdivision and then through leafs
idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r( tw, tw->model->node, 0, 1, tw->start, tw->end );
}
else {
// approximate the rotation with a series of straight line movements
// total length covered along circle
d = tw->radius * DEG2RAD( tw->angle );
// if more than one step
if ( d > CIRCLE_APPROXIMATION_LENGTH ) {
// number of steps for the approximation
numSteps = (int) (CIRCLE_APPROXIMATION_LENGTH / d);
// start of approximation
start = tw->start;
// trace circle approximation steps through the BSP tree
for ( i = 0; i < numSteps; i++ ) {
// calculate next point on approximated circle
rot.Set( tw->origin, tw->axis, tw->angle * ((float) (i+1) / numSteps) );
end = start * rot;
// trace through spatial subdivision and then through leafs
idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r( tw, tw->model->node, 0, 1, start, end );
// no need to continue if something was hit already
if ( tw->trace.fraction < 1.0f ) {
return;
}
start = end;
}
}
else {
start = tw->start;
}
// last step of the approximation
idCollisionModelManagerLocal::TraceThroughAxialBSPTree_r( tw, tw->model->node, 0, 1, start, tw->end );
}
}

File diff suppressed because it is too large Load Diff

1272
neo/d3xp/AF.cpp Normal file

File diff suppressed because it is too large Load Diff

120
neo/d3xp/AF.h Normal file
View File

@@ -0,0 +1,120 @@
/*
===========================================================================
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 __GAME_AF_H__
#define __GAME_AF_H__
/*
===============================================================================
Articulated figure controller.
===============================================================================
*/
typedef struct jointConversion_s {
int bodyId; // id of the body
jointHandle_t jointHandle; // handle of joint this body modifies
AFJointModType_t jointMod; // modify joint axis, origin or both
idVec3 jointBodyOrigin; // origin of body relative to joint
idMat3 jointBodyAxis; // axis of body relative to joint
} jointConversion_t;
typedef struct afTouch_s {
idEntity * touchedEnt;
idClipModel * touchedClipModel;
idAFBody * touchedByBody;
} afTouch_t;
class idAF {
public:
idAF();
~idAF();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void SetAnimator( idAnimator *a ) { animator = a; }
bool Load( idEntity *ent, const char *fileName );
bool IsLoaded() const { return isLoaded && self != NULL; }
const char * GetName() const { return name.c_str(); }
void SetupPose( idEntity *ent, int time );
void ChangePose( idEntity *ent, int time );
int EntitiesTouchingAF( afTouch_t touchList[ MAX_GENTITIES ] ) const;
void Start();
void StartFromCurrentPose( int inheritVelocityTime );
void Stop();
void Rest();
bool IsActive() const { return isActive; }
void SetConstraintPosition( const char *name, const idVec3 &pos );
idPhysics_AF * GetPhysics() { return &physicsObj; }
const idPhysics_AF * GetPhysics() const { return &physicsObj; }
idBounds GetBounds() const;
bool UpdateAnimation();
void GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis ) const;
void GetImpactInfo( idEntity *ent, int id, const idVec3 &point, impactInfo_t *info );
void ApplyImpulse( idEntity *ent, int id, const idVec3 &point, const idVec3 &impulse );
void AddForce( idEntity *ent, int id, const idVec3 &point, const idVec3 &force );
int BodyForClipModelId( int id ) const;
void SaveState( idDict &args ) const;
void LoadState( const idDict &args );
void AddBindConstraints();
void RemoveBindConstraints();
protected:
idStr name; // name of the loaded .af file
idPhysics_AF physicsObj; // articulated figure physics
idEntity * self; // entity using the animated model
idAnimator * animator; // animator on entity
int modifiedAnim; // anim to modify
idVec3 baseOrigin; // offset of base body relative to skeletal model origin
idMat3 baseAxis; // axis of base body relative to skeletal model origin
idList<jointConversion_t, TAG_AF> jointMods; // list with transforms from skeletal model joints to articulated figure bodies
idList<int, TAG_AF> jointBody; // table to find the nearest articulated figure body for a joint of the skeletal model
int poseTime; // last time the articulated figure was transformed to reflect the current animation pose
int restStartTime; // time the articulated figure came to rest
bool isLoaded; // true when the articulated figure is properly loaded
bool isActive; // true if the articulated figure physics is active
bool hasBindConstraints; // true if the bind constraints have been added
protected:
void SetBase( idAFBody *body, const idJointMat *joints );
void AddBody( idAFBody *body, const idJointMat *joints, const char *jointName, const AFJointModType_t mod );
bool LoadBody( const idDeclAF_Body *fb, const idJointMat *joints );
bool LoadConstraint( const idDeclAF_Constraint *fc );
bool TestSolid() const;
};
#endif /* !__GAME_AF_H__ */

3676
neo/d3xp/AFEntity.cpp Normal file

File diff suppressed because it is too large Load Diff

597
neo/d3xp/AFEntity.h Normal file
View File

@@ -0,0 +1,597 @@
/*
===========================================================================
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 __GAME_AFENTITY_H__
#define __GAME_AFENTITY_H__
/*
===============================================================================
idMultiModelAF
Entity using multiple separate visual models animated with a single
articulated figure. Only used for debugging!
===============================================================================
*/
const int GIB_DELAY = 200; // only gib this often to keep performace hits when blowing up several mobs
class idMultiModelAF : public idEntity {
public:
CLASS_PROTOTYPE( idMultiModelAF );
void Spawn();
~idMultiModelAF();
virtual void Think();
virtual void Present();
protected:
idPhysics_AF physicsObj;
void SetModelForId( int id, const idStr &modelName );
private:
idList<idRenderModel *, TAG_AF> modelHandles;
idList<int, TAG_AF> modelDefHandles;
};
/*
===============================================================================
idChain
Chain hanging down from the ceiling. Only used for debugging!
===============================================================================
*/
class idChain : public idMultiModelAF {
public:
CLASS_PROTOTYPE( idChain );
void Spawn();
protected:
void BuildChain( const idStr &name, const idVec3 &origin, float linkLength, float linkWidth, float density, int numLinks, bool bindToWorld = true );
};
/*
===============================================================================
idAFAttachment
===============================================================================
*/
class idAFAttachment : public idAnimatedEntity {
public:
CLASS_PROTOTYPE( idAFAttachment );
idAFAttachment();
virtual ~idAFAttachment();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void SetBody( idEntity *bodyEnt, const char *headModel, jointHandle_t attachJoint );
void ClearBody();
idEntity * GetBody() const;
virtual void Think();
virtual void Hide();
virtual void Show();
void PlayIdleAnim( int blendTime );
virtual void GetImpactInfo( idEntity *ent, int id, const idVec3 &point, impactInfo_t *info );
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 AddDamageEffect( const trace_t &collision, const idVec3 &velocity, const char *damageDefName );
void SetCombatModel();
idClipModel * GetCombatModel() const;
virtual void LinkCombat();
virtual void UnlinkCombat();
protected:
idEntity * body;
idClipModel * combatModel; // render model for hit detection of head
int idleAnim;
jointHandle_t attachJoint;
};
/*
===============================================================================
idAFEntity_Base
===============================================================================
*/
class idAFEntity_Base : public idAnimatedEntity {
public:
CLASS_PROTOTYPE( idAFEntity_Base );
idAFEntity_Base();
virtual ~idAFEntity_Base();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
virtual void AddDamageEffect( const trace_t &collision, const idVec3 &velocity, const char *damageDefName );
virtual void GetImpactInfo( idEntity *ent, int id, const idVec3 &point, impactInfo_t *info );
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 bool Collide( const trace_t &collision, const idVec3 &velocity );
virtual bool GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis );
virtual bool UpdateAnimationControllers();
virtual void FreeModelDef();
virtual bool LoadAF();
bool IsActiveAF() const { return af.IsActive(); }
const char * GetAFName() const { return af.GetName(); }
idPhysics_AF * GetAFPhysics() { return af.GetPhysics(); }
void SetCombatModel();
idClipModel * GetCombatModel() const;
// contents of combatModel can be set to 0 or re-enabled (mp)
void SetCombatContents( bool enable );
virtual void LinkCombat();
virtual void UnlinkCombat();
int BodyForClipModelId( int id ) const;
void SaveState( idDict &args ) const;
void LoadState( const idDict &args );
void AddBindConstraints();
void RemoveBindConstraints();
virtual void ShowEditingDialog();
static void DropAFs( idEntity *ent, const char *type, idList<idEntity *> *list );
protected:
idAF af; // articulated figure
idClipModel * combatModel; // render model for hit detection
int combatModelContents;
idVec3 spawnOrigin; // spawn origin
idMat3 spawnAxis; // rotation axis used when spawned
int nextSoundTime; // next time this can make a sound
void Event_SetConstraintPosition( const char *name, const idVec3 &pos );
};
/*
===============================================================================
idAFEntity_Gibbable
===============================================================================
*/
extern const idEventDef EV_Gib;
extern const idEventDef EV_Gibbed;
class idAFEntity_Gibbable : public idAFEntity_Base {
public:
CLASS_PROTOTYPE( idAFEntity_Gibbable );
idAFEntity_Gibbable();
~idAFEntity_Gibbable();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Present();
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location );
void SetThrown( bool isThrown );
virtual bool Collide( const trace_t &collision, const idVec3 &velocity );
virtual void SpawnGibs( const idVec3 &dir, const char *damageDefName );
bool IsGibbed() { return gibbed; };
protected:
idRenderModel * skeletonModel;
int skeletonModelDefHandle;
bool gibbed;
bool wasThrown;
virtual void Gib( const idVec3 &dir, const char *damageDefName );
void InitSkeletonModel();
void Event_Gib( const char *damageDefName );
};
/*
===============================================================================
idAFEntity_Generic
===============================================================================
*/
class idAFEntity_Generic : public idAFEntity_Gibbable {
public:
CLASS_PROTOTYPE( idAFEntity_Generic );
idAFEntity_Generic();
~idAFEntity_Generic();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
void KeepRunningPhysics() { keepRunningPhysics = true; }
private:
void Event_Activate( idEntity *activator );
bool keepRunningPhysics;
};
/*
===============================================================================
idAFEntity_WithAttachedHead
===============================================================================
*/
class idAFEntity_WithAttachedHead : public idAFEntity_Gibbable {
public:
CLASS_PROTOTYPE( idAFEntity_WithAttachedHead );
idAFEntity_WithAttachedHead();
~idAFEntity_WithAttachedHead();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void SetupHead();
virtual void Think();
virtual void Hide();
virtual void Show();
virtual void ProjectOverlay( const idVec3 &origin, const idVec3 &dir, float size, const char *material );
virtual void LinkCombat();
virtual void UnlinkCombat();
protected:
virtual void Gib( const idVec3 &dir, const char *damageDefName );
public:
idEntityPtr<idAFAttachment> head;
void Event_Gib( const char *damageDefName );
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idAFEntity_Vehicle
===============================================================================
*/
class idAFEntity_Vehicle : public idAFEntity_Base {
public:
CLASS_PROTOTYPE( idAFEntity_Vehicle );
idAFEntity_Vehicle();
void Spawn();
void Use( idPlayer *player );
protected:
idPlayer * player;
jointHandle_t eyesJoint;
jointHandle_t steeringWheelJoint;
float wheelRadius;
float steerAngle;
float steerSpeed;
const idDeclParticle * dustSmoke;
float GetSteerAngle();
};
/*
===============================================================================
idAFEntity_VehicleSimple
===============================================================================
*/
class idAFEntity_VehicleSimple : public idAFEntity_Vehicle {
public:
CLASS_PROTOTYPE( idAFEntity_VehicleSimple );
idAFEntity_VehicleSimple();
~idAFEntity_VehicleSimple();
void Spawn();
virtual void Think();
protected:
idClipModel * wheelModel;
idAFConstraint_Suspension * suspension[4];
jointHandle_t wheelJoints[4];
float wheelAngles[4];
};
/*
===============================================================================
idAFEntity_VehicleFourWheels
===============================================================================
*/
class idAFEntity_VehicleFourWheels : public idAFEntity_Vehicle {
public:
CLASS_PROTOTYPE( idAFEntity_VehicleFourWheels );
idAFEntity_VehicleFourWheels();
void Spawn();
virtual void Think();
protected:
idAFBody * wheels[4];
idAFConstraint_Hinge * steering[2];
jointHandle_t wheelJoints[4];
float wheelAngles[4];
};
/*
===============================================================================
idAFEntity_VehicleSixWheels
===============================================================================
*/
class idAFEntity_VehicleSixWheels : public idAFEntity_Vehicle {
public:
CLASS_PROTOTYPE( idAFEntity_VehicleSixWheels );
idAFEntity_VehicleSixWheels();
void Spawn();
virtual void Think();
float force;
float velocity;
float steerAngle;
private:
idAFBody * wheels[6];
idAFConstraint_Hinge * steering[4];
jointHandle_t wheelJoints[6];
float wheelAngles[6];
};
/*
===============================================================================
idAFEntity_VehicleAutomated
===============================================================================
*/
class idAFEntity_VehicleAutomated : public idAFEntity_VehicleSixWheels {
public:
CLASS_PROTOTYPE( idAFEntity_VehicleAutomated );
void Spawn();
void PostSpawn();
virtual void Think();
private:
idEntity *waypoint;
float steeringSpeed;
float currentSteering;
float idealSteering;
float originHeight;
void Event_SetVelocity( float _velocity );
void Event_SetTorque( float _torque );
void Event_SetSteeringSpeed( float _steeringSpeed );
void Event_SetWayPoint( idEntity *_waypoint );
};
/*
===============================================================================
idAFEntity_SteamPipe
===============================================================================
*/
class idAFEntity_SteamPipe : public idAFEntity_Base {
public:
CLASS_PROTOTYPE( idAFEntity_SteamPipe );
idAFEntity_SteamPipe();
~idAFEntity_SteamPipe();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
private:
int steamBody;
float steamForce;
float steamUpForce;
idForce_Constant force;
renderEntity_t steamRenderEntity;
qhandle_t steamModelDefHandle;
void InitSteamRenderEntity();
};
/*
===============================================================================
idAFEntity_ClawFourFingers
===============================================================================
*/
class idAFEntity_ClawFourFingers : public idAFEntity_Base {
public:
CLASS_PROTOTYPE( idAFEntity_ClawFourFingers );
idAFEntity_ClawFourFingers();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
private:
idAFConstraint_Hinge * fingers[4];
void Event_SetFingerAngle( float angle );
void Event_StopFingers();
};
/**
* idHarvestable contains all of the code required to turn an entity into a harvestable
* entity. The entity must create an instance of this class and call the appropriate
* interface methods at the correct time.
*/
class idHarvestable : public idEntity {
public:
CLASS_PROTOTYPE( idHarvestable );
idHarvestable();
~idHarvestable();
void Spawn();
void Init(idEntity* parent);
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void SetParent(idEntity* parent);
void Think();
void Gib();
protected:
idEntityPtr<idEntity> parentEnt;
float triggersize;
idClipModel * trigger;
float giveDelay;
float removeDelay;
bool given;
idEntityPtr<idPlayer> player;
int startTime;
bool fxFollowPlayer;
idEntityPtr<idEntityFx> fx;
idStr fxOrient;
protected:
void BeginBurn();
void BeginFX();
void CalcTriggerBounds( float size, idBounds &bounds );
bool GetFxOrientationAxis(idMat3& mat);
void Event_SpawnHarvestTrigger();
void Event_Touch( idEntity *other, trace_t *trace );
} ;
/*
===============================================================================
idAFEntity_Harvest
===============================================================================
*/
class idAFEntity_Harvest : public idAFEntity_WithAttachedHead {
public:
CLASS_PROTOTYPE( idAFEntity_Harvest );
idAFEntity_Harvest();
~idAFEntity_Harvest();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
virtual void Gib( const idVec3 &dir, const char *damageDefName );
protected:
idEntityPtr<idHarvestable> harvestEnt;
protected:
void Event_SpawnHarvestEntity();
};
#endif /* !__GAME_AFENTITY_H__ */

537
neo/d3xp/Achievements.cpp Normal file
View File

@@ -0,0 +1,537 @@
/*
===========================================================================
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.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
#include "..\..\doomclassic\doom\doomdef.h"
idCVar achievements_Verbose( "achievements_Verbose", "1", CVAR_BOOL, "debug spam" );
idCVar g_demoMode( "g_demoMode", "0", CVAR_INTEGER, "this is a demo" );
bool idAchievementManager::cheatingDialogShown = false;
const struct achievementInfo_t {
int required;
bool lifetime; // true means the current count is stored on the player profile. Doesn't matter for single count achievements.
} achievementInfo [ACHIEVEMENTS_NUM] = {
{ 50, true }, // ACHIEVEMENT_EARN_ALL_50_TROPHIES
{ 1, true }, // ACHIEVEMENT_COMPLETED_DIFFICULTY_0
{ 1, true }, // ACHIEVEMENT_COMPLETED_DIFFICULTY_1
{ 1, true }, // ACHIEVEMENT_COMPLETED_DIFFICULTY_2
{ 1, true }, // ACHIEVEMENT_COMPLETED_DIFFICULTY_3
{ 64, false }, // ACHIEVEMENT_PDAS_BASE
{ 14, false }, // ACHIEVEMENT_WATCH_ALL_VIDEOS
{ 1, false }, // ACHIEVEMENT_KILL_MONSTER_WITH_1_HEALTH_LEFT
{ 35, false }, // ACHIEVEMENT_OPEN_ALL_LOCKERS
{ 20, true }, // ACHIEVEMENT_KILL_20_ENEMY_FISTS_HANDS
{ 1, true }, // ACHIEVEMENT_KILL_SCI_NEXT_TO_RCR
{ 1, true }, // ACHIEVEMENT_KILL_TWO_IMPS_ONE_SHOTGUN
{ 1, true }, // ACHIEVEMENT_SCORE_25000_TURKEY_PUNCHER
{ 50, true }, // ACHIEVEMENT_DESTROY_BARRELS
{ 1, true }, // ACHIEVEMENT_GET_BFG_FROM_SECURITY_OFFICE
{ 1, true }, // ACHIEVEMENT_COMPLETE_LEVEL_WITHOUT_TAKING_DMG
{ 1, true }, // ACHIEVEMENT_FIND_RAGE_LOGO
{ 1, true }, // ACHIEVEMENT_SPEED_RUN
{ 1, true }, // ACHIEVEMENT_DEFEAT_VAGARY_BOSS
{ 1, true }, // ACHIEVEMENT_DEFEAT_GUARDIAN_BOSS
{ 1, true }, // ACHIEVEMENT_DEFEAT_SABAOTH_BOSS
{ 1, true }, // ACHIEVEMENT_DEFEAT_CYBERDEMON_BOSS
{ 1, true }, // ACHIEVEMENT_SENTRY_BOT_ALIVE_TO_DEST
{ 20, true }, // ACHIEVEMENT_KILL_20_ENEMY_WITH_CHAINSAW
{ 1, true }, // ACHIEVEMENT_ID_LOGO_SECRET_ROOM
{ 1, true }, // ACHIEVEMENT_BLOODY_HANDWORK_OF_BETRUGER
{ 1, true }, // ACHIEVEMENT_TWO_DEMONS_FIGHT_EACH_OTHER
{ 20, true }, // ACHIEVEMENT_USE_SOUL_CUBE_TO_DEFEAT_20_ENEMY
{ 1, true }, // ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_0
{ 1, true }, // ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_1
{ 1, true }, // ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_2
{ 1, true }, // ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_3
{ 22, false }, // ACHIEVEMENT_PDAS_ROE
{ 1, true }, // ACHIEVEMENT_KILL_5_ENEMY_HELL_TIME
{ 1, true }, // ACHIEVEMENT_DEFEAT_HELLTIME_HUNTER
{ 1, true }, // ACHIEVEMENT_DEFEAT_BERSERK_HUNTER
{ 1, true }, // ACHIEVEMENT_DEFEAT_INVULNERABILITY_HUNTER
{ 1, true }, // ACHIEVEMENT_DEFEAT_MALEDICT_BOSS
{ 20, true }, // ACHIEVEMENT_GRABBER_KILL_20_ENEMY
{ 20, true }, // ACHIEVEMENT_ARTIFACT_WITH_BERSERK_PUNCH_20
{ 1, true }, // ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_0
{ 1, true }, // ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_1
{ 1, true }, // ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_2
{ 1, true }, // ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_3
{ 10, false }, // ACHIEVEMENT_PDAS_LE
{ 1, true }, // ACHIEVEMENT_MP_KILL_PLAYER_VIA_TELEPORT
{ 1, true }, // ACHIEVEMENT_MP_CATCH_ENEMY_IN_ROFC
{ 5, true }, // ACHIEVEMENT_MP_KILL_5_PLAYERS_USING_INVIS
{ 1, true }, // ACHIEVEMENT_MP_COMPLETE_MATCH_WITHOUT_DYING
{ 1, true }, // ACHIEVEMENT_MP_USE_BERSERK_TO_KILL_PLAYER
{ 1, true }, // ACHIEVEMENT_MP_KILL_2_GUYS_IN_ROOM_WITH_BFG
};
/*
================================================================================================
idAchievementManager
================================================================================================
*/
/*
========================
idAchievementManager::idAchievementManager
========================
*/
idAchievementManager::idAchievementManager() :
lastImpKilledTime( 0 ),
lastPlayerKilledTime( 0 ),
playerTookDamage( false ) {
counts.Zero();
ResetHellTimeKills();
}
/*
========================
idAchievementManager::Init
========================
*/
void idAchievementManager::Init( idPlayer * player ) {
owner = player;
SyncAchievments();
}
/*
========================
idAchievementManager::SyncAchievments
========================
*/
void idAchievementManager::SyncAchievments() {
idLocalUser * user = GetLocalUser();
if ( user == NULL || user->GetProfile() == NULL ) {
return;
}
// Set achievement counts
for ( int i = 0; i < counts.Num(); i++ ) {
if ( user->GetProfile()->GetAchievement( i ) ) {
counts[i] = achievementInfo[i].required;
} else if ( achievementInfo[i].lifetime ) {
counts[i] = user->GetStatInt( i );
}
}
}
/*
========================
idAchievementManager::GetLocalUser
========================
*/
idLocalUser * idAchievementManager::GetLocalUser() {
if ( !verify( owner != NULL ) ) {
return NULL;
}
return session->GetGameLobbyBase().GetLocalUserFromLobbyUser( gameLocal.lobbyUserIDs[ owner->GetEntityNumber() ] );
}
/*
========================
idAchievementManager::Save
========================
*/
void idAchievementManager::Save( idSaveGame * savefile ) const {
owner.Save( savefile );
for ( int i = 0; i < ACHIEVEMENTS_NUM; i++ ) {
savefile->WriteInt( counts[i] );
}
savefile->WriteInt( lastImpKilledTime );
savefile->WriteInt( lastPlayerKilledTime );
savefile->WriteBool( playerTookDamage );
savefile->WriteInt( currentHellTimeKills );
}
/*
========================
idAchievementManager::Restore
========================
*/
void idAchievementManager::Restore( idRestoreGame * savefile ) {
owner.Restore( savefile );
for ( int i = 0; i < ACHIEVEMENTS_NUM; i++ ) {
savefile->ReadInt( counts[i] );
}
savefile->ReadInt( lastImpKilledTime );
savefile->ReadInt( lastPlayerKilledTime );
savefile->ReadBool( playerTookDamage );
savefile->ReadInt( currentHellTimeKills );
SyncAchievments();
}
/*
========================
idAchievementManager::EventCompletesAchievement
========================
*/
void idAchievementManager::EventCompletesAchievement( const achievement_t eventId ) {
if ( g_demoMode.GetBool() ) {
return;
}
idLocalUser * localUser = GetLocalUser();
if ( localUser == NULL || localUser->GetProfile() == NULL ) {
// Send a Reliable Message to the User that needs to unlock this.
if ( owner != NULL ) {
int playerId = owner->entityNumber;
const int bufferSize = sizeof( playerId ) + sizeof( eventId );
byte buffer[ bufferSize ];
idBitMsg msg;
msg.InitWrite( buffer, bufferSize );
msg.WriteByte( playerId );
msg.WriteByte( eventId );
msg.WriteByteAlign();
idLib::Printf( "Host Sending Achievement\n");
session->GetActingGameStateLobbyBase().SendReliableToLobbyUser( gameLocal.lobbyUserIDs[ owner->entityNumber ], GAME_RELIABLE_MESSAGE_ACHIEVEMENT_UNLOCK, msg );
}
return; // Remote user or build game
}
// Check to see if we've already given the achievement.
// If so, don't do again because we don't want to autosave every time a trigger is hit
if ( localUser->GetProfile()->GetAchievement( eventId ) ) {
return;
}
#ifdef ID_RETAIL
if ( common->GetConsoleUsed() ) {
if ( !cheatingDialogShown ) {
common->Dialog().AddDialog( GDM_ACHIEVEMENTS_DISABLED_DUE_TO_CHEATING, DIALOG_ACCEPT, NULL, NULL, true );
cheatingDialogShown = true;
}
return;
}
#endif
counts[eventId]++;
if ( counts[eventId] >= achievementInfo[eventId].required ) {
session->GetAchievementSystem().AchievementUnlock( localUser, eventId );
} else {
if ( achievementInfo[eventId].lifetime ) {
localUser->SetStatInt( eventId, counts[eventId] );
}
}
}
/*
========================
idAchievementManager::IncrementHellTimeKills
========================
*/
void idAchievementManager::IncrementHellTimeKills() {
currentHellTimeKills++;
if ( currentHellTimeKills >= 5 ) {
EventCompletesAchievement( ACHIEVEMENT_KILL_5_ENEMY_HELL_TIME );
}
}
/*
========================
idAchievementManager::SavePersistentData
========================
*/
void idAchievementManager::SavePersistentData( idDict & playerInfo ) {
for ( int i = 0; i < ACHIEVEMENTS_NUM; ++i ) {
playerInfo.SetInt( va( "ach_%d", i ), counts[i] );
}
}
/*
========================
idAchievementManager::RestorePersistentData
========================
*/
void idAchievementManager::RestorePersistentData( const idDict & spawnArgs ) {
for( int i = 0; i < ACHIEVEMENTS_NUM; ++i ) {
counts[i] = spawnArgs.GetInt( va( "ach_%d", i), "0" );
}
}
/*
========================
idAchievementManager::LocalUser_CompleteAchievement
========================
*/
void idAchievementManager::LocalUser_CompleteAchievement( achievement_t id ) {
idLocalUser * localUser = session->GetSignInManager().GetMasterLocalUser();
// Check to see if we've already given the achievement.
// If so, don't do again because we don't want to autosave every time a trigger is hit
if( localUser == NULL || localUser->GetProfile()->GetAchievement( id ) ) {
return;
}
#ifdef ID_RETAIL
if ( common->GetConsoleUsed() ) {
if ( !cheatingDialogShown ) {
common->Dialog().AddDialog( GDM_ACHIEVEMENTS_DISABLED_DUE_TO_CHEATING, DIALOG_ACCEPT, NULL, NULL, true );
cheatingDialogShown = true;
}
return;
}
#endif
session->GetAchievementSystem().AchievementUnlock( localUser, id );
}
/*
========================
idAchievementManager::CheckDoomClassicsAchievements
Processed when the player finishes a level.
========================
*/
void idAchievementManager::CheckDoomClassicsAchievements( int killcount, int itemcount, int secretcount, int skill, int mission, int map, int episode, int totalkills, int totalitems, int totalsecret ) {
const skill_t difficulty = (skill_t)skill;
const currentGame_t currentGame = common->GetCurrentGame();
const GameMission_t expansion = (GameMission_t)mission;
idLocalUser * localUser = session->GetSignInManager().GetMasterLocalUser();
if ( localUser != NULL && localUser->GetProfile() != NULL ) {
// GENERAL ACHIEVEMENT UNLOCKING.
if( currentGame == DOOM_CLASSIC ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_NEOPHYTE_COMPLETE_ANY_LEVEL );
} else if( currentGame == DOOM2_CLASSIC ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_JUST_GETTING_STARTED_COMPLETE_ANY_LEVEL );
}
// Complete Any Level on Nightmare.
if ( difficulty == sk_nightmare && currentGame == DOOM_CLASSIC ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_NIGHTMARE_COMPLETE_ANY_LEVEL_NIGHTMARE );
}
const bool gotAllKills = killcount >= totalkills;
const bool gotAllItems = itemcount >= totalitems;
const bool gotAllSecrets = secretcount >= totalsecret;
if ( gotAllItems && gotAllKills && gotAllSecrets ) {
if( currentGame == DOOM_CLASSIC ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_BURNING_OUT_OF_CONTROL_COMPLETE_KILLS_ITEMS_SECRETS );
} else if( currentGame == DOOM2_CLASSIC ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_BURNING_OUT_OF_CONTROL_COMPLETE_KILLS_ITEMS_SECRETS );
}
}
// DOOM EXPANSION ACHIEVEMENTS
if( expansion == doom ) {
if( map == 8 ) {
// Medium or higher skill level.
if( difficulty >= sk_medium ) {
localUser->SetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_MEDIUM + ( episode - 1 ), 1 );
}
// Hard or higher skill level.
if( difficulty >= sk_hard ) {
localUser->SetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_HARD + ( episode - 1 ), 1 );
localUser->SetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_MEDIUM + ( episode - 1 ), 1 );
}
if ( difficulty == sk_nightmare ) {
localUser->SetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_HARD + ( episode - 1 ), 1 );
localUser->SetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_MEDIUM + ( episode - 1 ), 1 );
}
// Save the Settings.
localUser->SaveProfileSettings();
}
// Check to see if we've completed all episodes.
const int episode1completed = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_MEDIUM );
const int episode2completed = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_2_MEDIUM );
const int episode3completed = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_3_MEDIUM );
const int episode4completed = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_4_MEDIUM );
const int episode1completed_hard = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_1_HARD );
const int episode2completed_hard = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_2_HARD );
const int episode3completed_hard = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_3_HARD );
const int episode4completed_hard = localUser->GetStatInt( STAT_DOOM_COMPLETED_EPISODE_4_HARD );
if ( currentGame == DOOM_CLASSIC ) {
if ( episode1completed ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_EPISODE1_COMPLETE_MEDIUM );
}
if ( episode2completed ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_EPISODE2_COMPLETE_MEDIUM );
}
if ( episode3completed ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_EPISODE3_COMPLETE_MEDIUM );
}
if ( episode4completed ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_EPISODE4_COMPLETE_MEDIUM );
}
if ( episode1completed_hard && episode2completed_hard && episode3completed_hard && episode4completed_hard ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM1_RAMPAGE_COMPLETE_ALL_HARD );
}
}
} else if( expansion == doom2 ) {
if( map == 30 ) {
if ( currentGame == DOOM2_CLASSIC ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_FROM_EARTH_TO_HELL_COMPLETE_HELL_ON_EARTH );
if ( difficulty >= sk_hard ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_SUPERIOR_FIREPOWER_COMPLETE_ALL_HARD );
}
}
}
} else if( expansion == pack_nerve ) {
if( map == 8 ) {
if ( currentGame == DOOM2_CLASSIC ) {
LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_AND_BACK_AGAIN_COMPLETE_NO_REST );
}
}
}
}
}
/*
=================
AchievementsReset
=================
*/
CONSOLE_COMMAND( AchievementsReset, "Lock an achievement", NULL ) {
idLocalUser * user = session->GetSignInManager().GetMasterLocalUser();
if ( user == NULL ) {
idLib::Printf( "Must be signed in\n" );
return;
}
if ( args.Argc() == 1 ) {
for ( int i = 0; i < ACHIEVEMENTS_NUM; i++ ) {
user->SetStatInt( i, 0 );
session->GetAchievementSystem().AchievementLock( user, i );
}
} else {
int i = atoi( args.Argv( 1 ) );
user->SetStatInt( i, 0 );
session->GetAchievementSystem().AchievementLock( user, i );
}
user->SaveProfileSettings();
}
/*
=================
AchievementsUnlock
=================
*/
CONSOLE_COMMAND( AchievementsUnlock, "Unlock an achievement", NULL ) {
idLocalUser * user = session->GetSignInManager().GetMasterLocalUser();
if ( user == NULL ) {
idLib::Printf( "Must be signed in\n" );
return;
}
if ( args.Argc() == 1 ) {
for ( int i = 0; i < ACHIEVEMENTS_NUM; i++ ) {
user->SetStatInt( i, achievementInfo[i].required );
session->GetAchievementSystem().AchievementUnlock( user, i );
}
} else {
int i = atoi( args.Argv( 1 ) );
user->SetStatInt( i, achievementInfo[i].required );
session->GetAchievementSystem().AchievementUnlock( user, i );
}
user->SaveProfileSettings();
}
/*
=================
AchievementsList
=================
*/
CONSOLE_COMMAND( AchievementsList, "Lists achievements and status", NULL ) {
idPlayer * player = gameLocal.GetLocalPlayer();
idLocalUser * user = ( player == NULL ) ? session->GetSignInManager().GetMasterLocalUser() : session->GetGameLobbyBase().GetLocalUserFromLobbyUser( gameLocal.lobbyUserIDs[ player->GetEntityNumber() ] );
if ( user == NULL ) {
idLib::Printf( "Must be signed in\n" );
return;
}
idPlayerProfile * profile = user->GetProfile();
idArray<bool, 128> achievementState;
bool achievementStateValid = session->GetAchievementSystem().GetAchievementState( user, achievementState );
for ( int i = 0; i < ACHIEVEMENTS_NUM; i++ ) {
const char * pInfo = "";
if ( profile == NULL ) {
pInfo = S_COLOR_RED "unknown" S_COLOR_DEFAULT;
} else if ( !profile->GetAchievement( i ) ) {
pInfo = S_COLOR_YELLOW "locked" S_COLOR_DEFAULT;
} else {
pInfo = S_COLOR_GREEN "unlocked" S_COLOR_DEFAULT;
}
const char * sInfo = "";
if ( !achievementStateValid ) {
sInfo = S_COLOR_RED "unknown" S_COLOR_DEFAULT;
} else if ( !achievementState[i] ) {
sInfo = S_COLOR_YELLOW "locked" S_COLOR_DEFAULT;
} else {
sInfo = S_COLOR_GREEN "unlocked" S_COLOR_DEFAULT;
}
int count = 0;
if ( achievementInfo[i].lifetime ) {
count = user->GetStatInt( i );
} else if ( player != NULL ) {
count = player->GetAchievementManager().GetCount( (achievement_t) i );
} else {
count = 0;
}
achievementDescription_t data;
bool descriptionValid = session->GetAchievementSystem().GetAchievementDescription( user, i, data );
idLib::Printf( "%02d: %2d/%2d | %12.12s | %12.12s | %s%s\n", i, count, achievementInfo[i].required, pInfo, sInfo, descriptionValid ? data.hidden ? "(hidden) " : "" : "(unknown) ", descriptionValid ? data.name : "" );
}
}

184
neo/d3xp/Achievements.h Normal file
View File

@@ -0,0 +1,184 @@
/*
===========================================================================
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 __ACHIEVEMENTS_H__
#define __ACHIEVEMENTS_H__
enum achievement_t {
ACHIEVEMENT_INVALID = -1,
ACHIEVEMENT_EARN_ALL_50_TROPHIES, // 0 // DONE -- (automagic?)
ACHIEVEMENT_COMPLETED_DIFFICULTY_0, // 1 // DONE -- Recruit
ACHIEVEMENT_COMPLETED_DIFFICULTY_1, // 2 // DONE -- Marine
ACHIEVEMENT_COMPLETED_DIFFICULTY_2, // 3 // DONE -- Veteran
ACHIEVEMENT_COMPLETED_DIFFICULTY_3, // 4 // DONE -- Nightmare
ACHIEVEMENT_PDAS_BASE, // 5 // DONE --
ACHIEVEMENT_WATCH_ALL_VIDEOS, // 6 // DONE --
ACHIEVEMENT_KILL_MONSTER_WITH_1_HEALTH_LEFT, // 7 // DONE --
ACHIEVEMENT_OPEN_ALL_LOCKERS, // 8 // DONE --
ACHIEVEMENT_KILL_20_ENEMY_FISTS_HANDS, // 9 // DONE --- kill 20 enemies with fists & hands
ACHIEVEMENT_KILL_SCI_NEXT_TO_RCR, // 10 // DONE -----> ADD TARGET TO MAP kill scientist trapped next to reactor control room
ACHIEVEMENT_KILL_TWO_IMPS_ONE_SHOTGUN, // 11 // DONE --
ACHIEVEMENT_SCORE_25000_TURKEY_PUNCHER, // 12 // DONE --
ACHIEVEMENT_DESTROY_BARRELS, // 13 // DONE --
ACHIEVEMENT_GET_BFG_FROM_SECURITY_OFFICE, // 14 // DONE -----> ADD TARGET TO MAP
ACHIEVEMENT_COMPLETE_LEVEL_WITHOUT_TAKING_DMG, // 15 // DONE --
ACHIEVEMENT_FIND_RAGE_LOGO, // 16 // DONE -----> ADD TARGET TO MAP (jerry)
ACHIEVEMENT_SPEED_RUN, // 17 // DONE --
ACHIEVEMENT_DEFEAT_VAGARY_BOSS, // 18 // DONE --
ACHIEVEMENT_DEFEAT_GUARDIAN_BOSS, // 19 // DONE --
ACHIEVEMENT_DEFEAT_SABAOTH_BOSS, // 20 // DONE --
ACHIEVEMENT_DEFEAT_CYBERDEMON_BOSS, // 21 // DONE --
ACHIEVEMENT_SENTRY_BOT_ALIVE_TO_DEST, // 22 // DONE -----> ADD TARGET TO MAP
ACHIEVEMENT_KILL_20_ENEMY_WITH_CHAINSAW, // 23 // DONE --
ACHIEVEMENT_ID_LOGO_SECRET_ROOM, // 24 // DONE -----> ADD TARGET TO MAP
ACHIEVEMENT_BLOODY_HANDWORK_OF_BETRUGER, // 25 // DONE -----> ADD TARGET TO MAP
ACHIEVEMENT_TWO_DEMONS_FIGHT_EACH_OTHER, // 26 // DONE --
ACHIEVEMENT_USE_SOUL_CUBE_TO_DEFEAT_20_ENEMY, // 27 // DONE --
ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_0, // 28 // DONE -- Recruit
ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_1, // 29 // DONE -- Marine
ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_2, // 30 // DONE -- Veteran
ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_3, // 31 // DONE -- Nightmare
ACHIEVEMENT_PDAS_ROE, // 32 // DONE -- read all pdas in RoE
ACHIEVEMENT_KILL_5_ENEMY_HELL_TIME, // 33 // DONE --
ACHIEVEMENT_DEFEAT_HELLTIME_HUNTER, // 34 // DONE --
ACHIEVEMENT_DEFEAT_BERSERK_HUNTER, // 35 // DONE --
ACHIEVEMENT_DEFEAT_INVULNERABILITY_HUNTER, // 36 // DONE --
ACHIEVEMENT_DEFEAT_MALEDICT_BOSS, // 37 // DONE --
ACHIEVEMENT_GRABBER_KILL_20_ENEMY, // 38 // DONE --
ACHIEVEMENT_ARTIFACT_WITH_BERSERK_PUNCH_20, // 39 // DONE --
ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_0, // 40 // DONE -- Recruit
ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_1, // 41 // DONE -- Marine
ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_2, // 42 // DONE -- Veteran
ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_3, // 43 // DONE -- Nightmare
ACHIEVEMENT_PDAS_LE, // 44 // DONE -- read all pdas in LE
ACHIEVEMENT_MP_KILL_PLAYER_VIA_TELEPORT, // 45 // DONE --
ACHIEVEMENT_MP_CATCH_ENEMY_IN_ROFC, // 46 // DONE -- needs to be tested -- Reactor of Frag Chamber
ACHIEVEMENT_MP_KILL_5_PLAYERS_USING_INVIS, // 47 // DONE --
ACHIEVEMENT_MP_COMPLETE_MATCH_WITHOUT_DYING, // 48 // DONE --
ACHIEVEMENT_MP_USE_BERSERK_TO_KILL_PLAYER, // 49 // DONE --
ACHIEVEMENT_MP_KILL_2_GUYS_IN_ROOM_WITH_BFG, // 50 // DONE --
ACHIEVEMENT_DOOM1_NEOPHYTE_COMPLETE_ANY_LEVEL, // 51
ACHIEVEMENT_DOOM1_EPISODE1_COMPLETE_MEDIUM, // 52
ACHIEVEMENT_DOOM1_EPISODE2_COMPLETE_MEDIUM, // 53
ACHIEVEMENT_DOOM1_EPISODE3_COMPLETE_MEDIUM, // 54
ACHIEVEMENT_DOOM1_EPISODE4_COMPLETE_MEDIUM, // 55
ACHIEVEMENT_DOOM1_RAMPAGE_COMPLETE_ALL_HARD, // 56
ACHIEVEMENT_DOOM1_NIGHTMARE_COMPLETE_ANY_LEVEL_NIGHTMARE, // 57
ACHIEVEMENT_DOOM1_BURNING_OUT_OF_CONTROL_COMPLETE_KILLS_ITEMS_SECRETS, // 58
ACHIEVEMENT_DOOM2_JUST_GETTING_STARTED_COMPLETE_ANY_LEVEL, // 59
ACHIEVEMENT_DOOM2_FROM_EARTH_TO_HELL_COMPLETE_HELL_ON_EARTH, // 60
ACHIEVEMENT_DOOM2_AND_BACK_AGAIN_COMPLETE_NO_REST, // 61
ACHIEVEMENT_DOOM2_SUPERIOR_FIREPOWER_COMPLETE_ALL_HARD, // 62
ACHIEVEMENT_DOOM2_REALLY_BIG_GUN_FIND_BFG_SINGLEPLAYER, // 63
ACHIEVEMENT_DOOM2_BURNING_OUT_OF_CONTROL_COMPLETE_KILLS_ITEMS_SECRETS, // 64
ACHIEVEMENT_DOOM2_IMPORTANT_LOOKING_DOOR_FIND_ANY_SECRET, // 65
ACHIEVEMENTS_NUM,
STAT_DOOM_COMPLETED_EPISODE_1_MEDIUM,
STAT_DOOM_COMPLETED_EPISODE_2_MEDIUM,
STAT_DOOM_COMPLETED_EPISODE_3_MEDIUM,
STAT_DOOM_COMPLETED_EPISODE_4_MEDIUM,
STAT_DOOM_COMPLETED_EPISODE_1_HARD,
STAT_DOOM_COMPLETED_EPISODE_2_HARD,
STAT_DOOM_COMPLETED_EPISODE_3_HARD,
STAT_DOOM_COMPLETED_EPISODE_4_HARD,
};
compile_time_assert( ACHIEVEMENTS_NUM <= idPlayerProfile::MAX_PLAYER_PROFILE_STATS );
/*
================================================
idAchievementManager
Manages a List of Achievements associated with a particular Player.
This is setup to only have one achievement manager per game.
================================================
*/
class idAchievementManager {
public:
idAchievementManager();
void Init( idPlayer * player );
bool IsInitialized() const { return owner != NULL; }
// save games
void Save( idSaveGame * savefile ) const; // archives object for save game file
void Restore( idRestoreGame * savefile ); // unarchives object from save game file
// Debug tool to reset achievement state and counts
void Reset();
int GetCount( const achievement_t eventId ) const { return counts[eventId]; }
// Adds a count to the tracked number of events, these events can be applied to multiple achievements
void EventCompletesAchievement( const achievement_t eventId );
int GetLastImpKilledTime() { return lastImpKilledTime; }
void SetLastImpKilledTime( int time) { lastImpKilledTime = time; }
int GetLastPlayerKilledTime() { return lastPlayerKilledTime; }
void SetLastPlayerKilledTime( int time ) { lastPlayerKilledTime = time; }
bool GetPlayerTookDamage() { return playerTookDamage; }
void SetPlayerTookDamage( bool bl ) { playerTookDamage = bl; }
void IncrementHellTimeKills();
void ResetHellTimeKills() { currentHellTimeKills = 0; }
void SavePersistentData( idDict & playerInfo );
void RestorePersistentData( const idDict & spawnArgs );
static void LocalUser_CompleteAchievement( achievement_t id );
static void CheckDoomClassicsAchievements( int killcount, int itemcount, int secretcount, int skill, int mission, int map, int episode, int totalkills, int totalitems, int totalsecret );
private:
idEntityPtr< idPlayer > owner;
idArray<int, ACHIEVEMENTS_NUM> counts; // How many times has each achievement been given
int lastPlayerKilledTime;
int lastImpKilledTime;
bool playerTookDamage;
int currentHellTimeKills;
static bool cheatingDialogShown;
idLocalUser * GetLocalUser();
void SyncAchievments();
};
#endif // !__ACHIEVEMENTS_H__

3474
neo/d3xp/Actor.cpp Normal file

File diff suppressed because it is too large Load Diff

333
neo/d3xp/Actor.h Normal file
View File

@@ -0,0 +1,333 @@
/*
===========================================================================
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 __GAME_ACTOR_H__
#define __GAME_ACTOR_H__
/*
===============================================================================
idActor
===============================================================================
*/
extern const idEventDef AI_EnableEyeFocus;
extern const idEventDef AI_DisableEyeFocus;
extern const idEventDef EV_Footstep;
extern const idEventDef EV_FootstepLeft;
extern const idEventDef EV_FootstepRight;
extern const idEventDef EV_EnableWalkIK;
extern const idEventDef EV_DisableWalkIK;
extern const idEventDef EV_EnableLegIK;
extern const idEventDef EV_DisableLegIK;
extern const idEventDef AI_SetAnimPrefix;
extern const idEventDef AI_PlayAnim;
extern const idEventDef AI_PlayCycle;
extern const idEventDef AI_AnimDone;
extern const idEventDef AI_SetBlendFrames;
extern const idEventDef AI_GetBlendFrames;
extern const idEventDef AI_SetState;
class idDeclParticle;
class idAnimState {
public:
bool idleAnim;
idStr state;
int animBlendFrames;
int lastAnimBlendFrames; // allows override anims to blend based on the last transition time
public:
idAnimState();
~idAnimState();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Init( idActor *owner, idAnimator *_animator, int animchannel );
void Shutdown();
void SetState( const char *name, int blendFrames );
void StopAnim( int frames );
void PlayAnim( int anim );
void CycleAnim( int anim );
void BecomeIdle();
bool UpdateState();
bool Disabled() const;
void Enable( int blendFrames );
void Disable();
bool AnimDone( int blendFrames ) const;
bool IsIdle() const;
animFlags_t GetAnimFlags() const;
private:
idActor * self;
idAnimator * animator;
idThread * thread;
int channel;
bool disabled;
};
class idAttachInfo {
public:
idEntityPtr<idEntity> ent;
int channel;
};
typedef struct {
jointModTransform_t mod;
jointHandle_t from;
jointHandle_t to;
} copyJoints_t;
class idActor : public idAFEntity_Gibbable {
public:
CLASS_PROTOTYPE( idActor );
int team;
int rank; // monsters don't fight back if the attacker's rank is higher
idMat3 viewAxis; // view axis of the actor
idLinkList<idActor> enemyNode; // node linked into an entity's enemy list for quick lookups of who is attacking him
idLinkList<idActor> enemyList; // list of characters that have targeted the player as their enemy
public:
idActor();
virtual ~idActor();
void Spawn();
virtual void Restart();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Hide();
virtual void Show();
virtual int GetDefaultSurfaceType() const;
virtual void ProjectOverlay( const idVec3 &origin, const idVec3 &dir, float size, const char *material );
virtual bool LoadAF();
void SetupBody();
void CheckBlink();
virtual bool GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis );
virtual bool GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis );
// script state management
void ShutdownThreads();
virtual bool ShouldConstructScriptObjectAtSpawn() const;
virtual idThread * ConstructScriptObject();
void UpdateScript();
const function_t *GetScriptFunction( const char *funcname );
void SetState( const function_t *newState );
void SetState( const char *statename );
// vision testing
void SetEyeHeight( float height );
float EyeHeight() const;
idVec3 EyeOffset() const;
idVec3 GetEyePosition() const;
virtual void GetViewPos( idVec3 &origin, idMat3 &axis ) const;
void SetFOV( float fov );
bool CheckFOV( const idVec3 &pos ) const;
bool CanSee( idEntity *ent, bool useFOV ) const;
bool PointVisible( const idVec3 &point ) const;
virtual void GetAIAimTargets( const idVec3 &lastSightPos, idVec3 &headPos, idVec3 &chestPos );
// damage
void SetupDamageGroups();
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location );
int GetDamageForLocation( int damage, int location );
const char * GetDamageGroup( int location );
void ClearPain();
virtual bool Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
// model/combat model/ragdoll
void SetCombatModel();
idClipModel * GetCombatModel() const;
virtual void LinkCombat();
virtual void UnlinkCombat();
bool StartRagdoll();
void StopRagdoll();
virtual bool UpdateAnimationControllers();
// delta view angles to allow movers to rotate the view of the actor
const idAngles & GetDeltaViewAngles() const;
void SetDeltaViewAngles( const idAngles &delta );
bool HasEnemies() const;
idActor * ClosestEnemyToPoint( const idVec3 &pos );
idActor * EnemyWithMostHealth();
virtual bool OnLadder() const;
virtual void GetAASLocation( idAAS *aas, idVec3 &pos, int &areaNum ) const;
void Attach( idEntity *ent );
virtual void Teleport( const idVec3 &origin, const idAngles &angles, idEntity *destination );
virtual renderView_t * GetRenderView();
// animation state control
int GetAnim( int channel, const char *name );
void UpdateAnimState();
void SetAnimState( int channel, const char *name, int blendFrames );
const char * GetAnimState( int channel ) const;
bool InAnimState( int channel, const char *name ) const;
const char * WaitState() const;
void SetWaitState( const char *_waitstate );
bool AnimDone( int channel, int blendFrames ) const;
virtual void SpawnGibs( const idVec3 &dir, const char *damageDefName );
idEntity* GetHeadEntity() { return head.GetEntity(); };
protected:
friend class idAnimState;
float fovDot; // cos( fovDegrees )
idVec3 eyeOffset; // offset of eye relative to physics origin
idVec3 modelOffset; // offset of visual model relative to the physics origin
idAngles deltaViewAngles; // delta angles relative to view input angles
int pain_debounce_time; // next time the actor can show pain
int pain_delay; // time between playing pain sound
int pain_threshold; // how much damage monster can take at any one time before playing pain animation
idStrList damageGroups; // body damage groups
idList<float, TAG_ACTOR> damageScale; // damage scale per damage gruop
bool use_combat_bbox; // whether to use the bounding box for combat collision
idEntityPtr<idAFAttachment> head;
idList<copyJoints_t, TAG_ACTOR> copyJoints; // copied from the body animation to the head model
// state variables
const function_t *state;
const function_t *idealState;
// joint handles
jointHandle_t leftEyeJoint;
jointHandle_t rightEyeJoint;
jointHandle_t soundJoint;
idIK_Walk walkIK;
idStr animPrefix;
idStr painAnim;
// blinking
int blink_anim;
int blink_time;
int blink_min;
int blink_max;
// script variables
idThread * scriptThread;
idStr waitState;
idAnimState headAnim;
idAnimState torsoAnim;
idAnimState legsAnim;
bool allowPain;
bool allowEyeFocus;
bool finalBoss;
int painTime;
bool damageNotByFists;
idList<idAttachInfo, TAG_ACTOR> attachments;
int damageCap;
virtual void Gib( const idVec3 &dir, const char *damageDefName );
// removes attachments with "remove" set for when character dies
void RemoveAttachments();
// copies animation from body to head joints
void CopyJointsFromBodyToHead();
private:
void SyncAnimChannels( int channel, int syncToChannel, int blendFrames );
void FinishSetup();
void SetupHead();
void PlayFootStepSound();
void Event_EnableEyeFocus();
void Event_DisableEyeFocus();
void Event_Footstep();
void Event_EnableWalkIK();
void Event_DisableWalkIK();
void Event_EnableLegIK( int num );
void Event_DisableLegIK( int num );
void Event_SetAnimPrefix( const char *name );
void Event_LookAtEntity( idEntity *ent, float duration );
void Event_PreventPain( float duration );
void Event_DisablePain();
void Event_EnablePain();
void Event_GetPainAnim();
void Event_StopAnim( int channel, int frames );
void Event_PlayAnim( int channel, const char *name );
void Event_PlayCycle( int channel, const char *name );
void Event_IdleAnim( int channel, const char *name );
void Event_SetSyncedAnimWeight( int channel, int anim, float weight );
void Event_OverrideAnim( int channel );
void Event_EnableAnim( int channel, int blendFrames );
void Event_SetBlendFrames( int channel, int blendFrames );
void Event_GetBlendFrames( int channel );
void Event_AnimState( int channel, const char *name, int blendFrames );
void Event_GetAnimState( int channel );
void Event_InAnimState( int channel, const char *name );
void Event_FinishAction( const char *name );
void Event_AnimDone( int channel, int blendFrames );
void Event_HasAnim( int channel, const char *name );
void Event_CheckAnim( int channel, const char *animname );
void Event_ChooseAnim( int channel, const char *animname );
void Event_AnimLength( int channel, const char *animname );
void Event_AnimDistance( int channel, const char *animname );
void Event_HasEnemies();
void Event_NextEnemy( idEntity *ent );
void Event_ClosestEnemyToPoint( const idVec3 &pos );
void Event_StopSound( int channel, int netsync );
void Event_SetNextState( const char *name );
void Event_SetState( const char *name );
void Event_GetState();
void Event_GetHead();
void Event_SetDamageGroupScale( const char* groupName, float scale);
void Event_SetDamageGroupScaleAll( float scale );
void Event_GetDamageGroupScale( const char* groupName );
void Event_SetDamageCap( float _damageCap );
void Event_SetWaitState( const char* waitState);
void Event_GetWaitState();
};
#endif /* !__GAME_ACTOR_H__ */

436
neo/d3xp/AimAssist.cpp Normal file
View File

@@ -0,0 +1,436 @@
/*
===========================================================================
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.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
/*
================================================================================================
Contains the AimAssist implementation.
================================================================================================
*/
idCVar aa_targetAimAssistEnable ( "aa_targetAimAssistEnable", "0", CVAR_BOOL | CVAR_ARCHIVE, "Enables/Disables the entire Aim Assist system" );
idCVar aa_targetAdhesionEnable ( "aa_targetAdhesionEnable", "1", CVAR_BOOL, "Enables Target Adhesion" );
idCVar aa_targetFrictionEnable ( "aa_targetFrictionEnable", "1", CVAR_BOOL, "Enables Target Friction" );
// Selection
idCVar aa_targetMaxDistance ( "aa_targetMaxDistance", "3000", CVAR_FLOAT, "The Maximum Distance away for a target to be considered for adhesion, friction and target lock-to" );
idCVar aa_targetSelectionRadius ( "aa_targetSelectionRadius", "128.0", CVAR_FLOAT, "Radius used to select targets for auto aiming" );
// Adhesion
idCVar aa_targetAdhesionRadius ( "aa_targetAdhesionRadius", "96.0", CVAR_FLOAT, "Radius used to apply adhesion amount" );
idCVar aa_targetAdhesionYawSpeedMax ( "aa_targetAdhesionYawSpeedMax", "0.6", CVAR_FLOAT, "Max Yaw Adhesion Speed" );
idCVar aa_targetAdhesionPitchSpeedMax ( "aa_targetAdhesionPitchSpeedMax", "0.6", CVAR_FLOAT, "Max Pitch Adhesion Speed" );
idCVar aa_targetAdhesionContributionPctMax ( "aa_targetAdhesionContributionPctMax", "0.25", CVAR_FLOAT, "Max Adhesion Contribution Percentage - Range 0.0 - 1.0" );
idCVar aa_targetAdhesionPlayerSpeedThreshold ( "aa_targetAdhesionPlayerSpeedThreshold", "10.0", CVAR_FLOAT, "Speed Threshold that determines how fast the player needs to move before adhesion is allowed to kick in" );
// Friction
idCVar aa_targetFrictionMaxDistance ( "aa_targetFrictionMaxDistance", "1024.0", CVAR_FLOAT, "Minimum Distance Friction takes effect" );
idCVar aa_targetFrictionOptimalDistance ( "aa_targetFrictionOptimalDistance", "768.0", CVAR_FLOAT, "Optimal Distance for Friction to take an effect" );
idCVar aa_targetFrictionRadius ( "aa_targetFrictionRadius", "96.0", CVAR_FLOAT, "Friction Collision Sphere Radius" );
idCVar aa_targetFrictionOptimalRadius ( "aa_targetFrictionOptimalRadius", "192.0", CVAR_FLOAT, "Friction Collision Sphere Radius when at Optimal Distance" );
idCVar aa_targetFrictionMultiplierMin ( "aa_targetFrictionMultiplierMin", "1.0", CVAR_FLOAT, "Minimum Friction Scalar" );
idCVar aa_targetFrictionMultiplierMax ( "aa_targetFrictionMultiplierMax", "0.4", CVAR_FLOAT, "Maximum Friction Scalar" );
/*
========================
idAimAssist::Init
========================
*/
void idAimAssist::Init( idPlayer *player_ ) {
player = player_;
angleCorrection = ang_zero;
frictionScalar = 1.0f;
lastTargetPos = vec3_zero;
}
/*
========================
idAimAssist::Update
========================
*/
void idAimAssist::Update() {
angleCorrection = ang_zero;
UpdateNewAimAssist();
}
/*
========================
idAimAssist::UpdateNewAimAssist
========================
*/
void idAimAssist::UpdateNewAimAssist() {
angleCorrection = ang_zero;
frictionScalar = 1.0f;
idEntity* lastTarget = targetEntity;
targetEntity = NULL;
// is aim assisting allowed? If not then just bail out
if ( !aa_targetAimAssistEnable.GetBool() ) {
return;
}
bool forceLastTarget = false;
idVec3 targetPos;
idEntity * entity = NULL;
if ( forceLastTarget ) {
entity = lastTarget;
targetPos = lastTargetPos;
} else {
entity = FindAimAssistTarget( targetPos );
}
if ( entity != NULL ) {
UpdateFriction( entity, targetPos );
// by default we don't allow adhesion when we are standing still
const float playerMovementSpeedThreshold = Square( aa_targetAdhesionPlayerSpeedThreshold.GetFloat() );
float playerSpeed = player->GetPhysics()->GetLinearVelocity().LengthSqr();
// only allow adhesion on actors (ai) or players. Disallow adhesion on any static world entities such as explosive barrels
if ( playerSpeed > playerMovementSpeedThreshold ) {
UpdateAdhesion( entity, targetPos );
}
targetEntity = entity;
}
lastTargetPos = targetPos;
}
/*
========================
idAimAssist::FindAimAssistTarget
========================
*/
idEntity* idAimAssist::FindAimAssistTarget( idVec3& targetPos ) {
if ( player == NULL ) {
return NULL;
}
//TO DO: Make this faster
//TO DO: Defer Traces
idEntity * optimalTarget = NULL;
float currentBestScore = -idMath::INFINITY;
targetPos = vec3_zero;
idVec3 cameraPos;
idMat3 cameraAxis;
player->GetViewPos( cameraPos, cameraAxis );
float maxDistanceSquared = Square( aa_targetMaxDistance.GetFloat() );
idVec3 dirToTarget;
float distanceToTargetSquared;
idVec3 primaryTargetPos;
idVec3 secondaryTargetPos;
for ( idEntity * entity = gameLocal.aimAssistEntities.Next(); entity != NULL; entity = entity->aimAssistNode.Next() ) {
if ( !entity->IsActive() ) {
continue;
}
if ( entity->IsHidden() ) {
continue;
}
if ( entity->IsType( idActor::Type ) ) {
idActor * actor = static_cast<idActor *>( entity );
if ( actor->team == player->team ) {
// In DM, LMS, and Tourney, all players are on the same team
if ( gameLocal.gameType == GAME_CTF || gameLocal.gameType == GAME_TDM || gameLocal.gameType == GAME_SP ) {
continue;
}
}
}
if ( entity->IsType( idAI::Type ) ) {
idAI * aiEntity = static_cast<idAI *>( entity );
if ( aiEntity->ReactionTo( player ) == ATTACK_IGNORE ) {
continue;
}
}
// check whether we have a valid target position for this entity - skip it if we don't
if ( !ComputeTargetPos( entity, primaryTargetPos, secondaryTargetPos ) ) {
continue;
}
// is it close enough to us
dirToTarget = primaryTargetPos-cameraPos;
distanceToTargetSquared = dirToTarget.LengthSqr();
if ( distanceToTargetSquared > maxDistanceSquared ) {
continue;
}
// Compute a score in the range of 0..1 for how much are looking towards the target.
idVec3 forward = cameraAxis[ 0 ];
forward.Normalize();
dirToTarget.Normalize();
float ViewDirDotTargetDir = idMath::ClampFloat( -1.0f, 1.0f, forward * dirToTarget ); // compute the dot and clamp to account for floating point error
// throw out anything thats outside of weapon's global FOV.
if ( ViewDirDotTargetDir < 0.0f ) {
continue;
}
// to be consistent we always use the primaryTargetPos to compute the score for this entity
float computedScore = ComputeEntityAimAssistScore( primaryTargetPos, cameraPos, cameraAxis );
// check if the current score beats our current best score and we have line of sight to it.
if ( computedScore > currentBestScore ) {
// determine if the current target is in our line of sight
trace_t tr;
gameLocal.clip.TracePoint( tr, cameraPos, primaryTargetPos, MASK_MONSTERSOLID, player );
// did our trace fail?
if ( ( ( tr.fraction < 1.0f ) && ( tr.c.entityNum != entity->entityNumber ) ) || ( tr.fraction >= 1.0f ) ) {
// if the collision test failed for the primary position -- check the secondary position
trace_t tr2;
gameLocal.clip.TracePoint( tr2, cameraPos, secondaryTargetPos, MASK_MONSTERSOLID, player );
if ( ( ( tr2.fraction < 1.0f ) && ( tr2.c.entityNum != entity->entityNumber ) ) || ( tr2.fraction >= 1.0f ) ) {
// if the secondary position is also not visible then give up
continue;
}
// we can see the secondary target position so we should consider this entity but use
// the secondary position as the target position
targetPos = secondaryTargetPos;
} else {
targetPos = primaryTargetPos;
}
// if we got here then this is our new best score
optimalTarget = entity;
currentBestScore = computedScore;
}
}
return optimalTarget;
}
/*
========================
idAimAssist::ComputeEntityAimAssistScore
========================
*/
float idAimAssist::ComputeEntityAimAssistScore( const idVec3& targetPos, const idVec3& cameraPos, const idMat3& cameraAxis ) {
float score = 0.0f;
idVec3 dirToTarget = targetPos - cameraPos;
float distanceToTarget = dirToTarget.Length();
// Compute a score in the range of 0..1 for how much are looking towards the target.
idVec3 forward = cameraAxis[0];
forward.Normalize();
dirToTarget.Normalize();
float ViewDirDotTargetDir = idMath::ClampFloat( 0.0f, 1.0f, forward * dirToTarget ); // compute the dot and clamp to account for floating point error
// the more we look at the target the higher our score
score = ViewDirDotTargetDir;
// weigh the score from the view angle higher than the distance score
static float aimWeight = 0.8f;
score *= aimWeight;
// Add a score of 0..1 for how close the target is to the player
if ( distanceToTarget < aa_targetMaxDistance.GetFloat() ) {
float distanceScore = 1.0f - ( distanceToTarget / aa_targetMaxDistance.GetFloat() );
float distanceWeight = 1.0f - aimWeight;
score += ( distanceScore * distanceWeight );
}
return score * 1000.0f;
}
/*
========================
idAimAssist::UpdateAdhesion
========================
*/
void idAimAssist::UpdateAdhesion( idEntity* pTarget, const idVec3& targetPos ) {
if ( !aa_targetAdhesionEnable.GetBool() ) {
return;
}
if ( !pTarget ) {
return;
}
float contributionPctMax = aa_targetAdhesionContributionPctMax.GetFloat();
idVec3 cameraPos;
idMat3 cameraAxis;
player->GetViewPos(cameraPos, cameraAxis);
idAngles cameraViewAngles = cameraAxis.ToAngles();
cameraViewAngles.Normalize180();
idVec3 cameraViewPos = cameraPos;
idVec3 dirToTarget = targetPos - cameraViewPos;
float distanceToTarget = dirToTarget.Length();
idAngles aimAngles = dirToTarget.ToAngles();
aimAngles.Normalize180();
// find the delta
aimAngles -= cameraViewAngles;
// clamp velocities to some max values
aimAngles.yaw = idMath::ClampFloat( -aa_targetAdhesionYawSpeedMax.GetFloat(), aa_targetAdhesionYawSpeedMax.GetFloat(), aimAngles.yaw );
aimAngles.pitch = idMath::ClampFloat( -aa_targetAdhesionPitchSpeedMax.GetFloat(), aa_targetAdhesionPitchSpeedMax.GetFloat(), aimAngles.pitch );
idVec3 forward = cameraAxis[0];
forward.Normalize();
dirToTarget.Normalize();
float ViewDirDotTargetDir = idMath::ClampFloat( 0.0f, 1.0f, forward * dirToTarget ); // compute the dot and clamp to account for floating point error
float aimLength = ViewDirDotTargetDir * distanceToTarget;
idVec3 aimPoint = cameraPos + ( forward * aimLength );
float delta = idMath::Sqrt( Square( distanceToTarget ) - Square( aimLength ) );
float contribution = idMath::ClampFloat( 0.0f, contributionPctMax, 1.0f - ( delta / aa_targetAdhesionRadius.GetFloat() ) );
angleCorrection.yaw = aimAngles.yaw * contribution;
angleCorrection.pitch = aimAngles.pitch * contribution;
}
/*
========================
idAimAssist::ComputeFrictionRadius
========================
*/
float idAimAssist::ComputeFrictionRadius( float distanceToTarget ) {
if ( ( distanceToTarget <= idMath::FLT_SMALLEST_NON_DENORMAL ) || distanceToTarget > aa_targetFrictionMaxDistance.GetFloat() ) {
return aa_targetFrictionRadius.GetFloat();
}
float distanceContributionScalar = ( aa_targetFrictionOptimalDistance.GetFloat() > 0.0f ) ? ( distanceToTarget / aa_targetFrictionOptimalDistance.GetFloat() ) : 0.0f;
if ( distanceToTarget > aa_targetFrictionOptimalDistance.GetFloat() ) {
const float range = idMath::ClampFloat( 0.0f, aa_targetFrictionMaxDistance.GetFloat(), aa_targetFrictionMaxDistance.GetFloat() - aa_targetFrictionOptimalDistance.GetFloat() );
if ( range > idMath::FLT_SMALLEST_NON_DENORMAL ) {
distanceContributionScalar = 1.0f - ( ( distanceToTarget - aa_targetFrictionOptimalDistance.GetFloat() ) / range );
}
}
return Lerp( aa_targetFrictionRadius.GetFloat(), aa_targetFrictionOptimalRadius.GetFloat(), distanceContributionScalar );
}
/*
========================
idAimAssist::UpdateFriction
========================
*/
void idAimAssist::UpdateFriction( idEntity* pTarget, const idVec3& targetPos ) {
if ( !aa_targetFrictionEnable.GetBool() ) {
return;
}
if ( pTarget == NULL ) {
return;
}
idVec3 cameraPos;
idMat3 cameraAxis;
player->GetViewPos(cameraPos, cameraAxis);
idVec3 dirToTarget = targetPos - cameraPos;
float distanceToTarget = dirToTarget.Length();
idVec3 forward = cameraAxis[0];
forward.Normalize();
dirToTarget.Normalize();
float ViewDirDotTargetDir = idMath::ClampFloat( 0.0f, 1.0f, forward * dirToTarget ); // compute the dot and clamp to account for floating point error
float aimLength = ViewDirDotTargetDir * distanceToTarget;
idVec3 aimPoint = cameraPos + ( forward * aimLength );
float delta = idMath::Sqrt( Square( distanceToTarget ) - Square( aimLength ) );
const float radius = ComputeFrictionRadius( distanceToTarget );
if ( delta < radius ) {
float alpha = 1.0f - ( delta / radius );
frictionScalar = Lerp( aa_targetFrictionMultiplierMin.GetFloat(), aa_targetFrictionMultiplierMax.GetFloat(), alpha );
}
}
/*
========================
idAimAssist::ComputeTargetPos
========================
*/
bool idAimAssist::ComputeTargetPos( idEntity* entity, idVec3& primaryTargetPos, idVec3& secondaryTargetPos ) {
primaryTargetPos = vec3_zero;
secondaryTargetPos = vec3_zero;
if ( entity == NULL ) {
return false;
}
// The target point on actors can now be either the head or the torso
idActor * actor = NULL;
if ( entity->IsType( idActor::Type ) ) {
actor = ( idActor *) entity;
}
if ( actor != NULL ) {
// Actor AimPoint
idVec3 torsoPos;
idVec3 headPos = actor->GetEyePosition();
if ( actor->GetHeadEntity() != NULL ) {
torsoPos = actor->GetHeadEntity()->GetPhysics()->GetOrigin();
} else {
const float offsetScale = 0.9f;
torsoPos = actor->GetPhysics()->GetOrigin() + ( actor->EyeOffset() * offsetScale );
}
primaryTargetPos = torsoPos;
secondaryTargetPos = headPos;
return true;
} else if ( entity->GetPhysics()->GetClipModel() != NULL ) {
const idBounds& box = entity->GetPhysics()->GetClipModel()->GetAbsBounds();
primaryTargetPos = box.GetCenter();
secondaryTargetPos = box.GetCenter();
return true;
}
return false;
}

75
neo/d3xp/AimAssist.h Normal file
View File

@@ -0,0 +1,75 @@
/*
===========================================================================
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 __AIMASSIST_H__
#define __AIMASSIST_H__
/*
================================================================================================
Contains the AimAssist declaration.
================================================================================================
*/
class idEntity;
class idPlayer;
/*
================================================
idAimAssist modifies the angle of Weapon firing to help the Player
hit a Target.
================================================
*/
class idAimAssist {
public:
idAimAssist() : angleCorrection( ang_zero ), frictionScalar( 1.0f ), lastTargetPos( vec3_zero ), player( NULL ) {}
void Init( idPlayer * player );
void Update();
void GetAngleCorrection( idAngles & correction ) const { correction = angleCorrection; }
float GetFrictionScalar () const { return frictionScalar; }
idEntity * GetLastTarget() { return targetEntity; }
idEntity * FindAimAssistTarget( idVec3 & targetPos );
private:
void UpdateNewAimAssist();
float ComputeEntityAimAssistScore( const idVec3 & targetPos, const idVec3 & cameraPos, const idMat3 & cameraAxis );
bool ComputeTargetPos( idEntity * pTarget, idVec3 & primaryTargetPos, idVec3 & secondaryTargetPos );
float ComputeFrictionRadius( float distanceToTarget );
void UpdateAdhesion( idEntity * pTarget, const idVec3 & targetPos);
void UpdateFriction( idEntity * pTarget, const idVec3 & targetPos);
idPlayer * player; // player associated with this object
idAngles angleCorrection; // the angle delta to apply for aim assistance
float frictionScalar; // friction scalar
idEntityPtr<idEntity> targetEntity; // the last target we had (updated every frame)
idVec3 lastTargetPos; // the last target position ( updated every frame );
};
#endif // !__AIMASSIST_H__

1386
neo/d3xp/BrittleFracture.cpp Normal file

File diff suppressed because it is too large Load Diff

141
neo/d3xp/BrittleFracture.h Normal file
View File

@@ -0,0 +1,141 @@
/*
===========================================================================
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 __GAME_BRITTLEFRACTURE_H__
#define __GAME_BRITTLEFRACTURE_H__
/*
===============================================================================
B-rep Brittle Fracture - Static entity using the boundary representation
of the render model which can fracture.
===============================================================================
*/
typedef struct shard_s {
idClipModel * clipModel;
idFixedWinding winding;
idList<idFixedWinding *, TAG_PHYSICS_BRITTLE> decals;
idList<bool> edgeHasNeighbour;
idList<struct shard_s *, TAG_PHYSICS_BRITTLE> neighbours;
idPhysics_RigidBody physicsObj;
int droppedTime;
bool atEdge;
int islandNum;
} shard_t;
class idBrittleFracture : public idEntity {
public:
CLASS_PROTOTYPE( idBrittleFracture );
idBrittleFracture();
virtual ~idBrittleFracture();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
virtual void Present();
virtual void Think();
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 AddDamageEffect( const trace_t &collision, const idVec3 &velocity, const char *damageDefName );
virtual void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
void ProjectDecal( const idVec3 &point, const idVec3 &dir, const int time, const char *damageDefName );
bool IsBroken() const;
enum {
EVENT_PROJECT_DECAL = idEntity::EVENT_MAXEVENTS,
EVENT_SHATTER,
EVENT_MAXEVENTS
};
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void ClientPredictionThink();
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
private:
// setttings
const idMaterial * material;
const idMaterial * decalMaterial;
float decalSize;
float maxShardArea;
float maxShatterRadius;
float minShatterRadius;
float linearVelocityScale;
float angularVelocityScale;
float shardMass;
float density;
float friction;
float bouncyness;
idStr fxFracture;
struct fractureEvent_s {
int eventType;
idVec3 point;
idVec3 vector;
};
idList<fractureEvent_s> storedEvents;
bool processStoredEvents;
idRenderModel * defaultRenderModel;
bool isXraySurface;
// state
idPhysics_StaticMulti physicsObj;
idList<shard_t *, TAG_PHYSICS_BRITTLE> shards;
idBounds bounds;
bool disableFracture;
// for rendering
mutable int lastRenderEntityUpdate;
mutable bool changed;
bool UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView ) const;
static bool ModelCallback( renderEntity_s *renderEntity, const renderView_t *renderView );
void AddShard( idClipModel *clipModel, idFixedWinding &w );
void RemoveShard( int index );
void DropShard( shard_t *shard, const idVec3 &point, const idVec3 &dir, const float impulse, const int time );
void Shatter( const idVec3 &point, const idVec3 &impulse, const int time );
void DropFloatingIslands( const idVec3 &point, const idVec3 &impulse, const int time );
void Break();
void Fracture_r( idFixedWinding &w, idRandom2 & random );
void CreateFractures( const idRenderModel *renderModel );
void FindNeighbours();
void Event_Activate( idEntity *activator );
void Event_Touch( idEntity *other, trace_t *trace );
};
#endif /* !__GAME_BRITTLEFRACTURE_H__ */

636
neo/d3xp/Camera.cpp Normal file
View File

@@ -0,0 +1,636 @@
/*
===========================================================================
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.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
/*
===============================================================================
idCamera
Base class for cameras
===============================================================================
*/
ABSTRACT_DECLARATION( idEntity, idCamera )
END_CLASS
/*
=====================
idCamera::Spawn
=====================
*/
void idCamera::Spawn() {
}
/*
=====================
idCamera::GetRenderView
=====================
*/
renderView_t *idCamera::GetRenderView() {
renderView_t *rv = idEntity::GetRenderView();
GetViewParms( rv );
return rv;
}
/***********************************************************************
idCameraView
***********************************************************************/
const idEventDef EV_Camera_SetAttachments( "<getattachments>", NULL );
CLASS_DECLARATION( idCamera, idCameraView )
EVENT( EV_Activate, idCameraView::Event_Activate )
EVENT( EV_Camera_SetAttachments, idCameraView::Event_SetAttachments )
END_CLASS
/*
===============
idCameraView::idCameraView
================
*/
idCameraView::idCameraView() {
fov = 90.0f;
attachedTo = NULL;
attachedView = NULL;
}
/*
===============
idCameraView::Save
================
*/
void idCameraView::Save( idSaveGame *savefile ) const {
savefile->WriteFloat( fov );
savefile->WriteObject( attachedTo );
savefile->WriteObject( attachedView );
}
/*
===============
idCameraView::Restore
================
*/
void idCameraView::Restore( idRestoreGame *savefile ) {
savefile->ReadFloat( fov );
savefile->ReadObject( reinterpret_cast<idClass *&>( attachedTo ) );
savefile->ReadObject( reinterpret_cast<idClass *&>( attachedView ) );
}
/*
===============
idCameraView::Event_SetAttachments
================
*/
void idCameraView::Event_SetAttachments( ) {
SetAttachment( &attachedTo, "attachedTo" );
SetAttachment( &attachedView, "attachedView" );
}
/*
===============
idCameraView::Event_Activate
================
*/
void idCameraView::Event_Activate( idEntity *activator ) {
if (spawnArgs.GetBool("trigger")) {
if (gameLocal.GetCamera() != this) {
if ( g_debugCinematic.GetBool() ) {
gameLocal.Printf( "%d: '%s' start\n", gameLocal.framenum, GetName() );
}
gameLocal.SetCamera(this);
} else {
if ( g_debugCinematic.GetBool() ) {
gameLocal.Printf( "%d: '%s' stop\n", gameLocal.framenum, GetName() );
}
gameLocal.SetCamera(NULL);
}
}
}
/*
=====================
idCameraView::Stop
=====================
*/
void idCameraView::Stop() {
if ( g_debugCinematic.GetBool() ) {
gameLocal.Printf( "%d: '%s' stop\n", gameLocal.framenum, GetName() );
}
gameLocal.SetCamera(NULL);
ActivateTargets( gameLocal.GetLocalPlayer() );
}
/*
=====================
idCameraView::Spawn
=====================
*/
void idCameraView::SetAttachment( idEntity **e, const char *p ) {
const char *cam = spawnArgs.GetString( p );
if ( strlen ( cam ) ) {
*e = gameLocal.FindEntity( cam );
}
}
/*
=====================
idCameraView::Spawn
=====================
*/
void idCameraView::Spawn() {
// if no target specified use ourself
const char *cam = spawnArgs.GetString("cameraTarget");
if ( strlen ( cam ) == 0) {
spawnArgs.Set("cameraTarget", spawnArgs.GetString("name"));
}
fov = spawnArgs.GetFloat("fov", "90");
PostEventMS( &EV_Camera_SetAttachments, 0 );
UpdateChangeableSpawnArgs(NULL);
}
/*
=====================
idCameraView::GetViewParms
=====================
*/
void idCameraView::GetViewParms( renderView_t *view ) {
assert( view );
if (view == NULL) {
return;
}
idVec3 dir;
idEntity *ent;
if ( attachedTo ) {
ent = attachedTo;
} else {
ent = this;
}
view->vieworg = ent->GetPhysics()->GetOrigin();
if ( attachedView ) {
dir = attachedView->GetPhysics()->GetOrigin() - view->vieworg;
dir.Normalize();
view->viewaxis = dir.ToMat3();
} else {
view->viewaxis = ent->GetPhysics()->GetAxis();
}
gameLocal.CalcFov( fov, view->fov_x, view->fov_y );
}
/*
===============================================================================
idCameraAnim
===============================================================================
*/
const idEventDef EV_Camera_Start( "start", NULL );
const idEventDef EV_Camera_Stop( "stop", NULL );
CLASS_DECLARATION( idCamera, idCameraAnim )
EVENT( EV_Thread_SetCallback, idCameraAnim::Event_SetCallback )
EVENT( EV_Camera_Stop, idCameraAnim::Event_Stop )
EVENT( EV_Camera_Start, idCameraAnim::Event_Start )
EVENT( EV_Activate, idCameraAnim::Event_Activate )
END_CLASS
/*
=====================
idCameraAnim::idCameraAnim
=====================
*/
idCameraAnim::idCameraAnim() {
threadNum = 0;
offset.Zero();
frameRate = 0;
cycle = 1;
starttime = 0;
activator = NULL;
}
/*
=====================
idCameraAnim::~idCameraAnim
=====================
*/
idCameraAnim::~idCameraAnim() {
if ( gameLocal.GetCamera() == this ) {
gameLocal.SetCamera( NULL );
}
}
/*
===============
idCameraAnim::Save
================
*/
void idCameraAnim::Save( idSaveGame *savefile ) const {
savefile->WriteInt( threadNum );
savefile->WriteVec3( offset );
savefile->WriteInt( frameRate );
savefile->WriteInt( starttime );
savefile->WriteInt( cycle );
activator.Save( savefile );
}
/*
===============
idCameraAnim::Restore
================
*/
void idCameraAnim::Restore( idRestoreGame *savefile ) {
savefile->ReadInt( threadNum );
savefile->ReadVec3( offset );
savefile->ReadInt( frameRate );
savefile->ReadInt( starttime );
savefile->ReadInt( cycle );
activator.Restore( savefile );
LoadAnim();
}
/*
=====================
idCameraAnim::Spawn
=====================
*/
void idCameraAnim::Spawn() {
if ( spawnArgs.GetVector( "old_origin", "0 0 0", offset ) ) {
offset = GetPhysics()->GetOrigin() - offset;
} else {
offset.Zero();
}
// always think during cinematics
cinematic = true;
LoadAnim();
}
/*
================
idCameraAnim::Load
================
*/
void idCameraAnim::LoadAnim() {
int version;
idLexer parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS | LEXFL_NOSTRINGCONCAT );
idToken token;
int numFrames;
int numCuts;
int i;
idStr filename;
const char *key;
key = spawnArgs.GetString( "anim" );
if ( !key ) {
gameLocal.Error( "Missing 'anim' key on '%s'", name.c_str() );
}
filename = spawnArgs.GetString( va( "anim %s", key ) );
if ( !filename.Length() ) {
gameLocal.Error( "Missing 'anim %s' key on '%s'", key, name.c_str() );
}
filename.SetFileExtension( MD5_CAMERA_EXT );
if ( !parser.LoadFile( filename ) ) {
gameLocal.Error( "Unable to load '%s' on '%s'", filename.c_str(), name.c_str() );
}
cameraCuts.Clear();
cameraCuts.SetGranularity( 1 );
camera.Clear();
camera.SetGranularity( 1 );
parser.ExpectTokenString( MD5_VERSION_STRING );
version = parser.ParseInt();
if ( version != MD5_VERSION ) {
parser.Error( "Invalid version %d. Should be version %d\n", version, MD5_VERSION );
}
// skip the commandline
parser.ExpectTokenString( "commandline" );
parser.ReadToken( &token );
// parse num frames
parser.ExpectTokenString( "numFrames" );
numFrames = parser.ParseInt();
if ( numFrames <= 0 ) {
parser.Error( "Invalid number of frames: %d", numFrames );
}
// parse framerate
parser.ExpectTokenString( "frameRate" );
frameRate = parser.ParseInt();
if ( frameRate <= 0 ) {
parser.Error( "Invalid framerate: %d", frameRate );
}
// parse num cuts
parser.ExpectTokenString( "numCuts" );
numCuts = parser.ParseInt();
if ( ( numCuts < 0 ) || ( numCuts > numFrames ) ) {
parser.Error( "Invalid number of camera cuts: %d", numCuts );
}
// parse the camera cuts
parser.ExpectTokenString( "cuts" );
parser.ExpectTokenString( "{" );
cameraCuts.SetNum( numCuts );
for( i = 0; i < numCuts; i++ ) {
cameraCuts[ i ] = parser.ParseInt();
if ( ( cameraCuts[ i ] < 1 ) || ( cameraCuts[ i ] >= numFrames ) ) {
parser.Error( "Invalid camera cut" );
}
}
parser.ExpectTokenString( "}" );
// parse the camera frames
parser.ExpectTokenString( "camera" );
parser.ExpectTokenString( "{" );
camera.SetNum( numFrames );
for( i = 0; i < numFrames; i++ ) {
parser.Parse1DMatrix( 3, camera[ i ].t.ToFloatPtr() );
parser.Parse1DMatrix( 3, camera[ i ].q.ToFloatPtr() );
camera[ i ].fov = parser.ParseFloat();
}
parser.ExpectTokenString( "}" );
}
/*
===============
idCameraAnim::Start
================
*/
void idCameraAnim::Start() {
cycle = spawnArgs.GetInt( "cycle" );
if ( !cycle ) {
cycle = 1;
}
if ( g_debugCinematic.GetBool() ) {
gameLocal.Printf( "%d: '%s' start\n", gameLocal.framenum, GetName() );
}
starttime = gameLocal.time;
gameLocal.SetCamera( this );
BecomeActive( TH_THINK );
// if the player has already created the renderview for this frame, have him update it again so that the camera starts this frame
if ( gameLocal.GetLocalPlayer()->GetRenderView()->time[TIME_GROUP2] == gameLocal.fast.time ) {
gameLocal.GetLocalPlayer()->CalculateRenderView();
}
}
/*
=====================
idCameraAnim::Stop
=====================
*/
void idCameraAnim::Stop() {
if ( gameLocal.GetCamera() == this ) {
if ( g_debugCinematic.GetBool() ) {
gameLocal.Printf( "%d: '%s' stop\n", gameLocal.framenum, GetName() );
}
BecomeInactive( TH_THINK );
gameLocal.SetCamera( NULL );
if ( threadNum ) {
idThread::ObjectMoveDone( threadNum, this );
threadNum = 0;
}
ActivateTargets( activator.GetEntity() );
}
}
/*
=====================
idCameraAnim::Think
=====================
*/
void idCameraAnim::Think() {
}
/*
=====================
idCameraAnim::GetViewParms
=====================
*/
void idCameraAnim::GetViewParms( renderView_t *view ) {
int realFrame;
int frame;
int frameTime;
float lerp;
float invlerp;
cameraFrame_t *camFrame;
int i;
int cut;
idQuat q1, q2, q3;
assert( view );
if ( !view ) {
return;
}
if ( camera.Num() == 0 ) {
// we most likely are in the middle of a restore
// FIXME: it would be better to fix it so this doesn't get called during a restore
return;
}
SetTimeState ts( timeGroup );
frameTime = ( gameLocal.time - starttime ) * frameRate;
frame = frameTime / 1000;
lerp = ( frameTime % 1000 ) * 0.001f;
// skip any frames where camera cuts occur
realFrame = frame;
cut = 0;
for( i = 0; i < cameraCuts.Num(); i++ ) {
if ( frame < cameraCuts[ i ] ) {
break;
}
frame++;
cut++;
}
if ( g_debugCinematic.GetBool() ) {
int prevFrameTime = ( gameLocal.previousTime - starttime ) * frameRate;
int prevFrame = prevFrameTime / 1000;
int prevCut;
prevCut = 0;
for( i = 0; i < cameraCuts.Num(); i++ ) {
if ( prevFrame < cameraCuts[ i ] ) {
break;
}
prevFrame++;
prevCut++;
}
if ( prevCut != cut ) {
gameLocal.Printf( "%d: '%s' cut %d\n", gameLocal.framenum, GetName(), cut );
}
}
// clamp to the first frame. also check if this is a one frame anim. one frame anims would end immediately,
// but since they're mainly used for static cams anyway, just stay on it infinitely.
if ( ( frame < 0 ) || ( camera.Num() < 2 ) ) {
view->viewaxis = camera[ 0 ].q.ToQuat().ToMat3();
view->vieworg = camera[ 0 ].t + offset;
view->fov_x = camera[ 0 ].fov;
} else if ( frame > camera.Num() - 2 ) {
if ( cycle > 0 ) {
cycle--;
}
if ( cycle != 0 ) {
// advance start time so that we loop
starttime += ( ( camera.Num() - cameraCuts.Num() ) * 1000 ) / frameRate;
GetViewParms( view );
return;
}
Stop();
if ( gameLocal.GetCamera() != NULL ) {
// we activated another camera when we stopped, so get it's viewparms instead
gameLocal.GetCamera()->GetViewParms( view );
return;
} else {
// just use our last frame
camFrame = &camera[ camera.Num() - 1 ];
view->viewaxis = camFrame->q.ToQuat().ToMat3();
view->vieworg = camFrame->t + offset;
view->fov_x = camFrame->fov;
}
} else if ( lerp == 0.0f ) {
camFrame = &camera[ frame ];
view->viewaxis = camFrame[ 0 ].q.ToMat3();
view->vieworg = camFrame[ 0 ].t + offset;
view->fov_x = camFrame[ 0 ].fov;
} else {
camFrame = &camera[ frame ];
invlerp = 1.0f - lerp;
q1 = camFrame[ 0 ].q.ToQuat();
q2 = camFrame[ 1 ].q.ToQuat();
q3.Slerp( q1, q2, lerp );
view->viewaxis = q3.ToMat3();
view->vieworg = camFrame[ 0 ].t * invlerp + camFrame[ 1 ].t * lerp + offset;
view->fov_x = camFrame[ 0 ].fov * invlerp + camFrame[ 1 ].fov * lerp;
}
gameLocal.CalcFov( view->fov_x, view->fov_x, view->fov_y );
// setup the pvs for this frame
UpdatePVSAreas( view->vieworg );
#if 0
static int lastFrame = 0;
static idVec3 lastFrameVec( 0.0f, 0.0f, 0.0f );
if ( gameLocal.time != lastFrame ) {
gameRenderWorld->DebugBounds( colorCyan, idBounds( view->vieworg ).Expand( 16.0f ), vec3_origin, 1 );
gameRenderWorld->DebugLine( colorRed, view->vieworg, view->vieworg + idVec3( 0.0f, 0.0f, 2.0f ), 10000, false );
gameRenderWorld->DebugLine( colorCyan, lastFrameVec, view->vieworg, 10000, false );
gameRenderWorld->DebugLine( colorYellow, view->vieworg + view->viewaxis[ 0 ] * 64.0f, view->vieworg + view->viewaxis[ 0 ] * 66.0f, 10000, false );
gameRenderWorld->DebugLine( colorOrange, view->vieworg + view->viewaxis[ 0 ] * 64.0f, view->vieworg + view->viewaxis[ 0 ] * 64.0f + idVec3( 0.0f, 0.0f, 2.0f ), 10000, false );
lastFrameVec = view->vieworg;
lastFrame = gameLocal.time;
}
#endif
if ( g_showcamerainfo.GetBool() ) {
gameLocal.Printf( "^5Frame: ^7%d/%d\n\n\n", realFrame + 1, camera.Num() - cameraCuts.Num() );
}
}
/*
===============
idCameraAnim::Event_Activate
================
*/
void idCameraAnim::Event_Activate( idEntity *_activator ) {
activator = _activator;
if ( thinkFlags & TH_THINK ) {
Stop();
} else {
Start();
}
}
/*
===============
idCameraAnim::Event_Start
================
*/
void idCameraAnim::Event_Start() {
Start();
}
/*
===============
idCameraAnim::Event_Stop
================
*/
void idCameraAnim::Event_Stop() {
Stop();
}
/*
================
idCameraAnim::Event_SetCallback
================
*/
void idCameraAnim::Event_SetCallback() {
if ( ( gameLocal.GetCamera() == this ) && !threadNum ) {
threadNum = idThread::CurrentThreadNum();
idThread::ReturnInt( true );
} else {
idThread::ReturnInt( false );
}
}

132
neo/d3xp/Camera.h Normal file
View File

@@ -0,0 +1,132 @@
/*
===========================================================================
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 __GAME_CAMERA_H__
#define __GAME_CAMERA_H__
/*
===============================================================================
Camera providing an alternative view of the level.
===============================================================================
*/
class idCamera : public idEntity {
public:
ABSTRACT_PROTOTYPE( idCamera );
void Spawn();
virtual void GetViewParms( renderView_t *view ) = 0;
virtual renderView_t * GetRenderView();
virtual void Stop(){} ;
};
/*
===============================================================================
idCameraView
===============================================================================
*/
class idCameraView : public idCamera {
public:
CLASS_PROTOTYPE( idCameraView );
idCameraView();
// save games
void Save( idSaveGame *savefile ) const; // archives object for save game file
void Restore( idRestoreGame *savefile ); // unarchives object from save game file
void Spawn( );
virtual void GetViewParms( renderView_t *view );
virtual void Stop();
protected:
void Event_Activate( idEntity *activator );
void Event_SetAttachments();
void SetAttachment( idEntity **e, const char *p );
float fov;
idEntity *attachedTo;
idEntity *attachedView;
};
/*
===============================================================================
A camera which follows a path defined by an animation.
===============================================================================
*/
typedef struct {
idCQuat q;
idVec3 t;
float fov;
} cameraFrame_t;
class idCameraAnim : public idCamera {
public:
CLASS_PROTOTYPE( idCameraAnim );
idCameraAnim();
~idCameraAnim();
// save games
void Save( idSaveGame *savefile ) const; // archives object for save game file
void Restore( idRestoreGame *savefile ); // unarchives object from save game file
void Spawn();
virtual void GetViewParms( renderView_t *view );
private:
int threadNum;
idVec3 offset;
int frameRate;
int starttime;
int cycle;
idList<int> cameraCuts;
idList<cameraFrame_t> camera;
idEntityPtr<idEntity> activator;
void Start();
void Stop();
void Think();
void LoadAnim();
void Event_Start();
void Event_Stop();
void Event_SetCallback();
void Event_Activate( idEntity *activator );
};
#endif /* !__GAME_CAMERA_H__ */

185
neo/d3xp/EndLevel.cpp Normal file
View File

@@ -0,0 +1,185 @@
/*
===========================================================================
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.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
/*
game_endlevel.cpp
This entity is targeted to complete a level, and it also handles
running the stats and moving the camera.
*/
CLASS_DECLARATION( idEntity, idTarget_EndLevel )
EVENT( EV_Activate, idTarget_EndLevel::Event_Trigger )
END_CLASS
/*
================
idTarget_EndLevel::Spawn
================
*/
void idTarget_EndLevel::Spawn( void ) {
idStr guiName;
gui = NULL;
noGui = spawnArgs.GetBool("noGui");
if (!noGui) {
spawnArgs.GetString( "guiName", "guis/EndLevel.gui", guiName );
if (guiName.Length()) {
gui = idUserInterface::FindGui( guiName, true, false, true );
}
}
buttonsReleased = false;
readyToExit = false;
exitCommand = "";
}
/*
================
idTarget_EndLevel::~idTarget_EndLevel()
================
*/
idTarget_EndLevel::~idTarget_EndLevel() {
//FIXME: need to go to smart ptrs for gui allocs or the unique method
//delete gui;
}
/*
================
idTarget_EndLevel::Event_Trigger
================
*/
void idTarget_EndLevel::Event_Trigger( idEntity *activator ) {
if ( gameLocal.endLevel ) {
return;
}
// mark the endLevel, which will modify some game actions
// and pass control to us for drawing the stats and camera position
gameLocal.endLevel = this;
// grab the activating player view position
idPlayer *player = (idPlayer *)(activator);
initialViewOrg = player->GetEyePosition();
initialViewAngles = idVec3( player->viewAngles[0], player->viewAngles[1], player->viewAngles[2] );
// kill all the sounds
gameSoundWorld->StopAllSounds();
if ( noGui ) {
readyToExit = true;
}
}
/*
================
idTarget_EndLevel::Draw
================
*/
void idTarget_EndLevel::Draw() {
if (noGui) {
return;
}
renderView_t renderView;
memset( &renderView, 0, sizeof( renderView ) );
renderView.width = SCREEN_WIDTH;
renderView.height = SCREEN_HEIGHT;
renderView.x = 0;
renderView.y = 0;
renderView.fov_x = 90;
renderView.fov_y = gameLocal.CalcFovY( renderView.fov_x );
renderView.time = gameLocal.time;
#if 0
renderView.vieworg = initialViewOrg;
renderView.viewaxis = idAngles(initialViewAngles).toMat3();
#else
renderView.vieworg = renderEntity.origin;
renderView.viewaxis = renderEntity.axis;
#endif
gameRenderWorld->RenderScene( &renderView );
// draw the gui on top of the 3D view
gui->Redraw(gameLocal.time);
}
/*
================
idTarget_EndLevel::PlayerCommand
================
*/
void idTarget_EndLevel::PlayerCommand( int buttons ) {
if ( !( buttons & BUTTON_ATTACK ) ) {
buttonsReleased = true;
return;
}
if ( !buttonsReleased ) {
return;
}
// we will exit at the end of the next game frame
readyToExit = true;
}
/*
================
idTarget_EndLevel::ExitCommand
================
*/
const char *idTarget_EndLevel::ExitCommand() {
if ( !readyToExit ) {
return NULL;
}
idStr nextMap;
if (spawnArgs.GetString( "nextMap", "", nextMap )) {
sprintf( exitCommand, "map %s", nextMap.c_str() );
} else {
exitCommand = "";
}
return exitCommand;
}

66
neo/d3xp/EndLevel.h Normal file
View File

@@ -0,0 +1,66 @@
/*
===========================================================================
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.
===========================================================================
*/
class idTarget_EndLevel : public idEntity {
public:
CLASS_PROTOTYPE( idTarget_EndLevel );
void Spawn( void );
~idTarget_EndLevel();
void Draw();
// the endLevel will be responsible for drawing the entire screen
// when it is active
void PlayerCommand( int buttons );
// when an endlevel is active, plauer buttons get sent here instead
// of doing anything to the player, which will allow moving to
// the next level
const char *ExitCommand();
// the game will check this each frame, and return it to the
// session when there is something to give
private:
idStr exitCommand;
idVec3 initialViewOrg;
idVec3 initialViewAngles;
// set when the player triggers the exit
idUserInterface *gui;
bool buttonsReleased;
// don't skip out until buttons are released, then pressed
bool readyToExit;
bool noGui;
void Event_Trigger( idEntity *activator );
};

5858
neo/d3xp/Entity.cpp Normal file

File diff suppressed because it is too large Load Diff

711
neo/d3xp/Entity.h Normal file
View File

@@ -0,0 +1,711 @@
/*
===========================================================================
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 __GAME_ENTITY_H__
#define __GAME_ENTITY_H__
/*
===============================================================================
Game entity base class.
===============================================================================
*/
static const int DELAY_DORMANT_TIME = 3000;
extern const idEventDef EV_PostSpawn;
extern const idEventDef EV_FindTargets;
extern const idEventDef EV_Touch;
extern const idEventDef EV_Use;
extern const idEventDef EV_Activate;
extern const idEventDef EV_ActivateTargets;
extern const idEventDef EV_Hide;
extern const idEventDef EV_Show;
extern const idEventDef EV_GetShaderParm;
extern const idEventDef EV_SetShaderParm;
extern const idEventDef EV_SetOwner;
extern const idEventDef EV_GetAngles;
extern const idEventDef EV_SetAngles;
extern const idEventDef EV_SetLinearVelocity;
extern const idEventDef EV_SetAngularVelocity;
extern const idEventDef EV_SetSkin;
extern const idEventDef EV_StartSoundShader;
extern const idEventDef EV_StopSound;
extern const idEventDef EV_CacheSoundShader;
// Think flags
enum {
TH_ALL = -1,
TH_THINK = 1, // run think function each frame
TH_PHYSICS = 2, // run physics each frame
TH_ANIMATE = 4, // update animation each frame
TH_UPDATEVISUALS = 8, // update renderEntity
TH_UPDATEPARTICLES = 16
};
//
// Signals
// make sure to change script/doom_defs.script if you add any, or change their order
//
typedef enum {
SIG_TOUCH, // object was touched
SIG_USE, // object was used
SIG_TRIGGER, // object was activated
SIG_REMOVED, // object was removed from the game
SIG_DAMAGE, // object was damaged
SIG_BLOCKED, // object was blocked
SIG_MOVER_POS1, // mover at position 1 (door closed)
SIG_MOVER_POS2, // mover at position 2 (door open)
SIG_MOVER_1TO2, // mover changing from position 1 to 2
SIG_MOVER_2TO1, // mover changing from position 2 to 1
NUM_SIGNALS
} signalNum_t;
// FIXME: At some point we may want to just limit it to one thread per signal, but
// for now, I'm allowing multiple threads. We should reevaluate this later in the project
#define MAX_SIGNAL_THREADS 16 // probably overkill, but idList uses a granularity of 16
struct signal_t {
int threadnum;
const function_t *function;
};
class signalList_t {
public:
idList<signal_t, TAG_ENTITY> signal[ NUM_SIGNALS ];
};
/*
================================================
idNetEvent
Utility for detecting a bool state change:
-server calls ::Set
-client ::Get will return true (once only)
Useful because:
-Hides client from having to manually declare "last" state and manually checking against it
-using int counter prevents problems w/ dropped snapshots
(ie if we just serialized a bool to true for a single ss, if that ss is dropped,skipped,whatever
the client would never handle it. By incrementing a wrapped counter, we are guaranteed to detect
the state change no matter what happens at the net layer).
================================================
*/
template < int max >
struct idNetEvent {
idNetEvent() : count(0), lastCount(0) { }
void Set() { count = ( ( count + 1 ) % max ); }
bool Get() {
if ( count != lastCount ) {
lastCount = count;
return true;
}
return false;
}
void Serialize( idSerializer &ser ) {
if ( count >= max ) {
idLib::Warning("idNetEvent. count %d > max %d", count, max );
}
ser.SerializeUMax( count, max );
}
public:
static const int Maximum = max;
int count;
int lastCount;
};
typedef idNetEvent< 7 > netBoolEvent_t;
inline void WriteToBitMsg( const netBoolEvent_t & netEvent, idBitMsg & msg ) {
msg.WriteBits( netEvent.count, idMath::BitsForInteger( netBoolEvent_t::Maximum ) );
assert( netEvent.count <= netBoolEvent_t::Maximum );
}
inline void ReadFromBitMsg( netBoolEvent_t & netEvent, const idBitMsg & msg ) {
netEvent.count = msg.ReadBits( idMath::BitsForInteger( netBoolEvent_t::Maximum ) );
assert( netEvent.count <= netBoolEvent_t::Maximum );
}
class idEntity : public idClass {
public:
static const int MAX_PVS_AREAS = 4;
static const uint32 INVALID_PREDICTION_KEY = 0xFFFFFFFF;
int entityNumber; // index into the entity list
int entityDefNumber; // index into the entity def list
idLinkList<idEntity> spawnNode; // for being linked into spawnedEntities list
idLinkList<idEntity> activeNode; // for being linked into activeEntities list
idLinkList<idEntity> aimAssistNode; // linked into gameLocal.aimAssistEntities
idLinkList<idEntity> snapshotNode; // for being linked into snapshotEntities list
int snapshotChanged; // used to detect snapshot state changes
int snapshotBits; // number of bits this entity occupied in the last snapshot
bool snapshotStale; // Set to true if this entity is considered stale in the snapshot
idStr name; // name of entity
idDict spawnArgs; // key/value pairs used to spawn and initialize entity
idScriptObject scriptObject; // contains all script defined data for this entity
int thinkFlags; // TH_? flags
int dormantStart; // time that the entity was first closed off from player
bool cinematic; // during cinematics, entity will only think if cinematic is set
renderView_t * renderView; // for camera views from this entity
idEntity * cameraTarget; // any remoteRenderMap shaders will use this
idList< idEntityPtr<idEntity>, TAG_ENTITY > targets; // when this entity is activated these entities entity are activated
int health; // FIXME: do all objects really need health?
struct entityFlags_s {
bool notarget :1; // if true never attack or target this entity
bool noknockback :1; // if true no knockback from hits
bool takedamage :1; // if true this entity can be damaged
bool hidden :1; // if true this entity is not visible
bool bindOrientated :1; // if true both the master orientation is used for binding
bool solidForTeam :1; // if true this entity is considered solid when a physics team mate pushes entities
bool forcePhysicsUpdate :1; // if true always update from the physics whether the object moved or not
bool selected :1; // if true the entity is selected for editing
bool neverDormant :1; // if true the entity never goes dormant
bool isDormant :1; // if true the entity is dormant
bool hasAwakened :1; // before a monster has been awakened the first time, use full PVS for dormant instead of area-connected
bool networkSync :1; // if true the entity is synchronized over the network
bool grabbed :1; // if true object is currently being grabbed
bool skipReplication :1; // don't replicate this entity over the network.
} fl;
int timeGroup;
bool noGrab;
renderEntity_t xrayEntity;
qhandle_t xrayEntityHandle;
const idDeclSkin * xraySkin;
void DetermineTimeGroup( bool slowmo );
void SetGrabbedState( bool grabbed );
bool IsGrabbed();
public:
ABSTRACT_PROTOTYPE( idEntity );
idEntity();
~idEntity();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
const char * GetEntityDefName() const;
void SetName( const char *name );
const char * GetName() const;
virtual void UpdateChangeableSpawnArgs( const idDict *source );
int GetEntityNumber() const { return entityNumber; }
// 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();
// thinking
virtual void Think();
bool CheckDormant(); // dormant == on the active list, but out of PVS
virtual void DormantBegin(); // called when entity becomes dormant
virtual void DormantEnd(); // called when entity wakes from being dormant
bool IsActive() const;
void BecomeActive( int flags );
void BecomeInactive( int flags );
void UpdatePVSAreas( const idVec3 &pos );
void BecomeReplicated();
// visuals
virtual void Present();
virtual renderEntity_t *GetRenderEntity();
virtual int GetModelDefHandle();
virtual void SetModel( const char *modelname );
void SetSkin( const idDeclSkin *skin );
const idDeclSkin * GetSkin() const;
void SetShaderParm( int parmnum, float value );
virtual void SetColor( float red, float green, float blue );
virtual void SetColor( const idVec3 &color );
virtual void GetColor( idVec3 &out ) const;
virtual void SetColor( const idVec4 &color );
virtual void GetColor( idVec4 &out ) const;
virtual void FreeModelDef();
virtual void FreeLightDef();
virtual void Hide();
virtual void Show();
bool IsHidden() const;
void UpdateVisuals();
void UpdateModel();
void UpdateModelTransform();
virtual void ProjectOverlay( const idVec3 &origin, const idVec3 &dir, float size, const char *material );
int GetNumPVSAreas();
const int * GetPVSAreas();
void ClearPVSAreas();
bool PhysicsTeamInPVS( pvsHandle_t pvsHandle );
// animation
virtual bool UpdateAnimationControllers();
bool UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView );
static bool ModelCallback( renderEntity_s *renderEntity, const renderView_t *renderView );
virtual idAnimator * GetAnimator(); // returns animator object used by this entity
// sound
virtual bool CanPlayChatterSounds() const;
bool StartSound( const char *soundName, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length );
bool StartSoundShader( const idSoundShader *shader, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length );
void StopSound( const s_channelType channel, bool broadcast ); // pass SND_CHANNEL_ANY to stop all sounds
void SetSoundVolume( float volume );
void UpdateSound();
int GetListenerId() const;
idSoundEmitter * GetSoundEmitter() const;
void FreeSoundEmitter( bool immediate );
// entity binding
virtual void PreBind();
virtual void PostBind();
virtual void PreUnbind();
virtual void PostUnbind();
void JoinTeam( idEntity *teammember );
void Bind( idEntity *master, bool orientated );
void BindToJoint( idEntity *master, const char *jointname, bool orientated );
void BindToJoint( idEntity *master, jointHandle_t jointnum, bool orientated );
void BindToBody( idEntity *master, int bodyId, bool orientated );
void Unbind();
bool IsBound() const;
bool IsBoundTo( idEntity *master ) const;
idEntity * GetBindMaster() const;
jointHandle_t GetBindJoint() const;
int GetBindBody() const;
idEntity * GetTeamMaster() const;
idEntity * GetNextTeamEntity() const;
void ConvertLocalToWorldTransform( idVec3 &offset, idMat3 &axis );
idVec3 GetLocalVector( const idVec3 &vec ) const;
idVec3 GetLocalCoordinates( const idVec3 &vec ) const;
idVec3 GetWorldVector( const idVec3 &vec ) const;
idVec3 GetWorldCoordinates( const idVec3 &vec ) const;
bool GetMasterPosition( idVec3 &masterOrigin, idMat3 &masterAxis ) const;
void GetWorldVelocities( idVec3 &linearVelocity, idVec3 &angularVelocity ) const;
// physics
// set a new physics object to be used by this entity
void SetPhysics( idPhysics *phys );
// get the physics object used by this entity
idPhysics * GetPhysics() const;
// restore physics pointer for save games
void RestorePhysics( idPhysics *phys );
// run the physics for this entity
bool RunPhysics();
// Interpolates the physics, used on MP clients.
void InterpolatePhysics( const float fraction );
// InterpolatePhysics actually calls evaluate, this version doesn't.
void InterpolatePhysicsOnly( const float fraction, bool updateTeam = false );
// set the origin of the physics object (relative to bindMaster if not NULL)
void SetOrigin( const idVec3 &org );
// set the axis of the physics object (relative to bindMaster if not NULL)
void SetAxis( const idMat3 &axis );
// use angles to set the axis of the physics object (relative to bindMaster if not NULL)
void SetAngles( const idAngles &ang );
// get the floor position underneath the physics object
bool GetFloorPos( float max_dist, idVec3 &floorpos ) const;
// retrieves the transformation going from the physics origin/axis to the visual origin/axis
virtual bool GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis );
// retrieves the transformation going from the physics origin/axis to the sound origin/axis
virtual bool GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis );
// called from the physics object when colliding, should return true if the physics simulation should stop
virtual bool Collide( const trace_t &collision, const idVec3 &velocity );
// retrieves impact information, 'ent' is the entity retrieving the info
virtual void GetImpactInfo( idEntity *ent, int id, const idVec3 &point, impactInfo_t *info );
// apply an impulse to the physics object, 'ent' is the entity applying the impulse
virtual void ApplyImpulse( idEntity *ent, int id, const idVec3 &point, const idVec3 &impulse );
// add a force to the physics object, 'ent' is the entity adding the force
virtual void AddForce( idEntity *ent, int id, const idVec3 &point, const idVec3 &force );
// activate the physics object, 'ent' is the entity activating this entity
virtual void ActivatePhysics( idEntity *ent );
// returns true if the physics object is at rest
virtual bool IsAtRest() const;
// returns the time the physics object came to rest
virtual int GetRestStartTime() const;
// add a contact entity
virtual void AddContactEntity( idEntity *ent );
// remove a touching entity
virtual void RemoveContactEntity( idEntity *ent );
// damage
// 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 );
// 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.
virtual void DamageFeedback( idEntity *victim, idEntity *inflictor, int &damage );
// notifies this entity that it is in pain
virtual bool Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
// notifies this entity that is has been killed
virtual void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
// scripting
virtual bool ShouldConstructScriptObjectAtSpawn() const;
virtual idThread * ConstructScriptObject();
virtual void DeconstructScriptObject();
void SetSignal( signalNum_t signalnum, idThread *thread, const function_t *function );
void ClearSignal( idThread *thread, signalNum_t signalnum );
void ClearSignalThread( signalNum_t signalnum, idThread *thread );
bool HasSignal( signalNum_t signalnum ) const;
void Signal( signalNum_t signalnum );
void SignalEvent( idThread *thread, signalNum_t signalnum );
// gui
void TriggerGuis();
bool HandleGuiCommands( idEntity *entityGui, const char *cmds );
virtual bool HandleSingleGuiCommand( idEntity *entityGui, idLexer *src );
// targets
void FindTargets();
void RemoveNullTargets();
void ActivateTargets( idEntity *activator ) const;
// misc
virtual void Teleport( const idVec3 &origin, const idAngles &angles, idEntity *destination );
bool TouchTriggers() const;
idCurve_Spline<idVec3> *GetSpline() const;
virtual void ShowEditingDialog();
enum {
EVENT_STARTSOUNDSHADER,
EVENT_STOPSOUNDSHADER,
EVENT_MAXEVENTS
};
// Called on clients in an MP game, does the actual interpolation for the entity.
// This function will eventually replace ClientPredictionThink completely.
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void ClientPredictionThink();
virtual void WriteToSnapshot( idBitMsg &msg ) const;
void ReadFromSnapshot_Ex( const idBitMsg &msg );
virtual void ReadFromSnapshot( const idBitMsg &msg );
virtual bool ServerReceiveEvent( int event, int time, const idBitMsg &msg );
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
void WriteBindToSnapshot( idBitMsg &msg ) const;
void ReadBindFromSnapshot( const idBitMsg &msg );
void WriteColorToSnapshot( idBitMsg &msg ) const;
void ReadColorFromSnapshot( const idBitMsg &msg );
void WriteGUIToSnapshot( idBitMsg &msg ) const;
void ReadGUIFromSnapshot( const idBitMsg &msg );
void ServerSendEvent( int eventId, const idBitMsg *msg, bool saveEvent, lobbyUserID_t excluding = lobbyUserID_t() ) const;
void ClientSendEvent( int eventId, const idBitMsg *msg ) const;
void SetUseClientInterpolation( bool use ) { useClientInterpolation = use; }
void SetSkipReplication( const bool skip ) { fl.skipReplication = skip; }
bool GetSkipReplication() const { return fl.skipReplication; }
bool IsReplicated() const { return GetEntityNumber() < ENTITYNUM_FIRST_NON_REPLICATED; }
void CreateDeltasFromOldOriginAndAxis( const idVec3 & oldOrigin, const idMat3 & oldAxis );
void DecayOriginAndAxisDelta();
uint32 GetPredictedKey() { return predictionKey; }
void SetPredictedKey( uint32 key_ ) { predictionKey = key_; }
void FlagNewSnapshot();
idEntity* GetTeamChain() { return teamChain; }
// It is only safe to interpolate if this entity has received two snapshots.
enum interpolationBehavior_t {
USE_NO_INTERPOLATION,
USE_LATEST_SNAP_ONLY,
USE_INTERPOLATION
};
interpolationBehavior_t GetInterpolationBehavior() const { return interpolationBehavior; }
unsigned int GetNumSnapshotsReceived() const { return snapshotsReceived; }
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
idVec3 GetOriginDelta() const { return originDelta; }
idMat3 GetAxisDelta() const { return axisDelta; }
private:
idPhysics_Static defaultPhysicsObj; // default physics object
idPhysics * physics; // physics used for this entity
idEntity * bindMaster; // entity bound to if unequal NULL
jointHandle_t bindJoint; // joint bound to if unequal INVALID_JOINT
int bindBody; // body bound to if unequal -1
idEntity * teamMaster; // master of the physics team
idEntity * teamChain; // next entity in physics team
bool useClientInterpolation; // disables interpolation for some objects (handy for weapon world models)
int numPVSAreas; // number of renderer areas the entity covers
int PVSAreas[MAX_PVS_AREAS]; // numbers of the renderer areas the entity covers
signalList_t * signals;
int mpGUIState; // local cache to avoid systematic SetStateInt
uint32 predictionKey; // Unique key used to sync predicted ents (projectiles) in MP.
// Delta values that are set when the server or client disagree on where the render model should be. If this happens,
// they resolve it through DecayOriginAndAxisDelta()
idVec3 originDelta;
idMat3 axisDelta;
interpolationBehavior_t interpolationBehavior;
unsigned int snapshotsReceived;
private:
void FixupLocalizedStrings();
bool DoDormantTests(); // dormant == on the active list, but out of PVS
// physics
// initialize the default physics
void InitDefaultPhysics( const idVec3 &origin, const idMat3 &axis );
// update visual position from the physics
void UpdateFromPhysics( bool moveBack );
// get physics timestep
virtual int GetPhysicsTimeStep() const;
// entity binding
bool InitBind( idEntity *master ); // initialize an entity binding
void FinishBind(); // finish an entity binding
void RemoveBinds(); // deletes any entities bound to this object
void QuitTeam(); // leave the current team
void UpdatePVSAreas();
// events
void Event_GetName();
void Event_SetName( const char *name );
void Event_FindTargets();
void Event_ActivateTargets( idEntity *activator );
void Event_NumTargets();
void Event_GetTarget( float index );
void Event_RandomTarget( const char *ignore );
void Event_Bind( idEntity *master );
void Event_BindPosition( idEntity *master );
void Event_BindToJoint( idEntity *master, const char *jointname, float orientated );
void Event_Unbind();
void Event_RemoveBinds();
void Event_SpawnBind();
void Event_SetOwner( idEntity *owner );
void Event_SetModel( const char *modelname );
void Event_SetSkin( const char *skinname );
void Event_GetShaderParm( int parmnum );
void Event_SetShaderParm( int parmnum, float value );
void Event_SetShaderParms( float parm0, float parm1, float parm2, float parm3 );
void Event_SetColor( float red, float green, float blue );
void Event_GetColor();
void Event_IsHidden();
void Event_Hide();
void Event_Show();
void Event_CacheSoundShader( const char *soundName );
void Event_StartSoundShader( const char *soundName, int channel );
void Event_StopSound( int channel, int netSync );
void Event_StartSound( const char *soundName, int channel, int netSync );
void Event_FadeSound( int channel, float to, float over );
void Event_GetWorldOrigin();
void Event_SetWorldOrigin( idVec3 const &org );
void Event_GetOrigin();
void Event_SetOrigin( const idVec3 &org );
void Event_GetAngles();
void Event_SetAngles( const idAngles &ang );
void Event_SetLinearVelocity( const idVec3 &velocity );
void Event_GetLinearVelocity();
void Event_SetAngularVelocity( const idVec3 &velocity );
void Event_GetAngularVelocity();
void Event_SetSize( const idVec3 &mins, const idVec3 &maxs );
void Event_GetSize();
void Event_GetMins();
void Event_GetMaxs();
void Event_Touches( idEntity *ent );
void Event_SetGuiParm( const char *key, const char *val );
void Event_SetGuiFloat( const char *key, float f );
void Event_GetNextKey( const char *prefix, const char *lastMatch );
void Event_SetKey( const char *key, const char *value );
void Event_GetKey( const char *key );
void Event_GetIntKey( const char *key );
void Event_GetFloatKey( const char *key );
void Event_GetVectorKey( const char *key );
void Event_GetEntityKey( const char *key );
void Event_RestorePosition();
void Event_UpdateCameraTarget();
void Event_DistanceTo( idEntity *ent );
void Event_DistanceToPoint( const idVec3 &point );
void Event_StartFx( const char *fx );
void Event_WaitFrame();
void Event_Wait( float time );
void Event_HasFunction( const char *name );
void Event_CallFunction( const char *name );
void Event_SetNeverDormant( int enable );
void Event_SetGui( int guiNum, const char *guiName);
void Event_PrecacheGui( const char *guiName );
void Event_GetGuiParm(int guiNum, const char *key);
void Event_GetGuiParmFloat(int guiNum, const char *key);
void Event_GuiNamedEvent(int guiNum, const char *event);
};
/*
===============================================================================
Animated entity base class.
===============================================================================
*/
typedef struct damageEffect_s {
jointHandle_t jointNum;
idVec3 localOrigin;
idVec3 localNormal;
int time;
const idDeclParticle* type;
struct damageEffect_s * next;
} damageEffect_t;
class idAnimatedEntity : public idEntity {
public:
CLASS_PROTOTYPE( idAnimatedEntity );
idAnimatedEntity();
~idAnimatedEntity();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void ClientPredictionThink();
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void Think();
void UpdateAnimation();
virtual idAnimator * GetAnimator();
virtual void SetModel( const char *modelname );
bool GetJointWorldTransform( jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis );
bool GetJointTransformForAnim( jointHandle_t jointHandle, int animNum, int currentTime, idVec3 &offset, idMat3 &axis ) const;
virtual int GetDefaultSurfaceType() const;
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();
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
enum {
EVENT_ADD_DAMAGE_EFFECT = idEntity::EVENT_MAXEVENTS,
EVENT_MAXEVENTS
};
protected:
idAnimator animator;
damageEffect_t * damageEffects;
private:
void Event_GetJointHandle( const char *jointname );
void Event_ClearAllJoints();
void Event_ClearJoint( jointHandle_t jointnum );
void Event_SetJointPos( jointHandle_t jointnum, jointModTransform_t transform_type, const idVec3 &pos );
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 );
};
class SetTimeState {
bool activated;
bool previousFast;
bool fast;
public:
SetTimeState();
SetTimeState( int timeGroup );
~SetTimeState();
void PushState( int timeGroup );
};
ID_INLINE SetTimeState::SetTimeState() {
activated = false;
}
ID_INLINE SetTimeState::SetTimeState( int timeGroup ) {
activated = false;
PushState( timeGroup );
}
ID_INLINE void SetTimeState::PushState( int timeGroup ) {
// Don't mess with time in Multiplayer
if ( !common->IsMultiplayer() ) {
activated = true;
// determine previous fast setting
if ( gameLocal.time == gameLocal.slow.time ) {
previousFast = false;
} else {
previousFast = true;
}
// determine new fast setting
if ( timeGroup ) {
fast = true;
} else {
fast = false;
}
// set correct time
gameLocal.SelectTimeGroup( timeGroup );
}
}
ID_INLINE SetTimeState::~SetTimeState() {
if ( activated && !common->IsMultiplayer() ) {
// set previous correct time
gameLocal.SelectTimeGroup( previousFast );
}
}
#endif /* !__GAME_ENTITY_H__ */

833
neo/d3xp/Fx.cpp Normal file
View File

@@ -0,0 +1,833 @@
/*
===========================================================================
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.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
/*
===============================================================================
idEntityFx
===============================================================================
*/
const idEventDef EV_Fx_KillFx( "_killfx" );
const idEventDef EV_Fx_Action( "_fxAction", "e" ); // implemented by subclasses
CLASS_DECLARATION( idEntity, idEntityFx )
EVENT( EV_Activate, idEntityFx::Event_Trigger )
EVENT( EV_Fx_KillFx, idEntityFx::Event_ClearFx )
END_CLASS
/*
================
idEntityFx::Save
================
*/
void idEntityFx::Save( idSaveGame *savefile ) const {
int i;
savefile->WriteInt( started );
savefile->WriteInt( nextTriggerTime );
savefile->WriteFX( fxEffect );
savefile->WriteString( systemName );
savefile->WriteInt( actions.Num() );
for ( i = 0; i < actions.Num(); i++ ) {
if ( actions[i].lightDefHandle >= 0 ) {
savefile->WriteBool( true );
savefile->WriteRenderLight( actions[i].renderLight );
} else {
savefile->WriteBool( false );
}
if ( actions[i].modelDefHandle >= 0 ) {
savefile->WriteBool( true );
savefile->WriteRenderEntity( actions[i].renderEntity );
} else {
savefile->WriteBool( false );
}
savefile->WriteFloat( actions[i].delay );
savefile->WriteInt( actions[i].start );
savefile->WriteBool( actions[i].soundStarted );
savefile->WriteBool( actions[i].shakeStarted );
savefile->WriteBool( actions[i].decalDropped );
savefile->WriteBool( actions[i].launched );
}
}
/*
================
idEntityFx::Restore
================
*/
void idEntityFx::Restore( idRestoreGame *savefile ) {
int i;
int num;
bool hasObject;
savefile->ReadInt( started );
savefile->ReadInt( nextTriggerTime );
savefile->ReadFX( fxEffect );
savefile->ReadString( systemName );
savefile->ReadInt( num );
actions.SetNum( num );
for ( i = 0; i < num; i++ ) {
savefile->ReadBool( hasObject );
if ( hasObject ) {
savefile->ReadRenderLight( actions[i].renderLight );
actions[i].lightDefHandle = gameRenderWorld->AddLightDef( &actions[i].renderLight );
} else {
memset( &actions[i].renderLight, 0, sizeof( renderLight_t ) );
actions[i].lightDefHandle = -1;
}
savefile->ReadBool( hasObject );
if ( hasObject ) {
savefile->ReadRenderEntity( actions[i].renderEntity );
actions[i].modelDefHandle = gameRenderWorld->AddEntityDef( &actions[i].renderEntity );
} else {
memset( &actions[i].renderEntity, 0, sizeof( renderEntity_t ) );
actions[i].modelDefHandle = -1;
}
savefile->ReadFloat( actions[i].delay );
// let the FX regenerate the particleSystem
actions[i].particleSystem = -1;
savefile->ReadInt( actions[i].start );
savefile->ReadBool( actions[i].soundStarted );
savefile->ReadBool( actions[i].shakeStarted );
savefile->ReadBool( actions[i].decalDropped );
savefile->ReadBool( actions[i].launched );
}
}
/*
================
idEntityFx::Setup
================
*/
void idEntityFx::Setup( const char *fx ) {
if ( started >= 0 ) {
return; // already started
}
// early during MP Spawn() with no information. wait till we ReadFromSnapshot for more
if ( common->IsClient() && ( !fx || fx[0] == '\0' ) ) {
return;
}
systemName = fx;
started = 0;
fxEffect = static_cast<const idDeclFX *>( declManager->FindType( DECL_FX, systemName.c_str() ) );
if ( fxEffect ) {
idFXLocalAction localAction;
memset( &localAction, 0, sizeof( idFXLocalAction ) );
actions.AssureSize( fxEffect->events.Num(), localAction );
for( int i = 0; i<fxEffect->events.Num(); i++ ) {
const idFXSingleAction& fxaction = fxEffect->events[i];
idFXLocalAction& laction = actions[i];
if ( fxaction.random1 || fxaction.random2 ) {
laction.delay = fxaction.random1 + gameLocal.random.RandomFloat() * ( fxaction.random2 - fxaction.random1 );
} else {
laction.delay = fxaction.delay;
}
laction.start = -1;
laction.lightDefHandle = -1;
laction.modelDefHandle = -1;
laction.particleSystem = -1;
laction.shakeStarted = false;
laction.decalDropped = false;
laction.launched = false;
}
}
}
/*
================
idEntityFx::EffectName
================
*/
const char *idEntityFx::EffectName() {
return fxEffect ? fxEffect->GetName() : NULL;
}
/*
================
idEntityFx::Joint
================
*/
const char *idEntityFx::Joint() {
return fxEffect ? fxEffect->joint.c_str() : NULL;
}
/*
================
idEntityFx::CleanUp
================
*/
void idEntityFx::CleanUp() {
if ( !fxEffect ) {
return;
}
for( int i = 0; i < fxEffect->events.Num(); i++ ) {
const idFXSingleAction& fxaction = fxEffect->events[i];
idFXLocalAction& laction = actions[i];
CleanUpSingleAction( fxaction, laction );
}
}
/*
================
idEntityFx::CleanUpSingleAction
================
*/
void idEntityFx::CleanUpSingleAction( const idFXSingleAction& fxaction, idFXLocalAction& laction ) {
if ( laction.lightDefHandle != -1 && fxaction.sibling == -1 && fxaction.type != FX_ATTACHLIGHT ) {
gameRenderWorld->FreeLightDef( laction.lightDefHandle );
laction.lightDefHandle = -1;
}
if ( laction.modelDefHandle != -1 && fxaction.sibling == -1 && fxaction.type != FX_ATTACHENTITY ) {
gameRenderWorld->FreeEntityDef( laction.modelDefHandle );
laction.modelDefHandle = -1;
}
laction.start = -1;
}
/*
================
idEntityFx::Start
================
*/
void idEntityFx::Start( int time ) {
if ( !fxEffect ) {
return;
}
started = time;
for( int i = 0; i < fxEffect->events.Num(); i++ ) {
idFXLocalAction& laction = actions[i];
laction.start = time;
laction.soundStarted = false;
laction.shakeStarted = false;
laction.particleSystem = -1;
laction.decalDropped = false;
laction.launched = false;
}
}
/*
================
idEntityFx::Stop
================
*/
void idEntityFx::Stop() {
CleanUp();
started = -1;
}
/*
================
idEntityFx::Duration
================
*/
const int idEntityFx::Duration() {
int max = 0;
if ( !fxEffect ) {
return max;
}
for( int i = 0; i < fxEffect->events.Num(); i++ ) {
const idFXSingleAction& fxaction = fxEffect->events[i];
int d = ( fxaction.delay + fxaction.duration ) * 1000.0f;
if ( d > max ) {
max = d;
}
}
return max;
}
/*
================
idEntityFx::Done
================
*/
const bool idEntityFx::Done() {
if (started > 0 && gameLocal.time > started + Duration()) {
return true;
}
return false;
}
/*
================
idEntityFx::ApplyFade
================
*/
void idEntityFx::ApplyFade( const idFXSingleAction& fxaction, idFXLocalAction& laction, const int time, const int actualStart ) {
if ( fxaction.fadeInTime || fxaction.fadeOutTime ) {
float fadePct = (float)( time - actualStart ) / ( 1000.0f * ( ( fxaction.fadeInTime != 0 ) ? fxaction.fadeInTime : fxaction.fadeOutTime ) );
if (fadePct > 1.0) {
fadePct = 1.0;
}
if ( laction.modelDefHandle != -1 ) {
laction.renderEntity.shaderParms[SHADERPARM_RED] = (fxaction.fadeInTime) ? fadePct : 1.0f - fadePct;
laction.renderEntity.shaderParms[SHADERPARM_GREEN] = (fxaction.fadeInTime) ? fadePct : 1.0f - fadePct;
laction.renderEntity.shaderParms[SHADERPARM_BLUE] = (fxaction.fadeInTime) ? fadePct : 1.0f - fadePct;
gameRenderWorld->UpdateEntityDef( laction.modelDefHandle, &laction.renderEntity );
}
if ( laction.lightDefHandle != -1 ) {
laction.renderLight.shaderParms[SHADERPARM_RED] = fxaction.lightColor.x * ( (fxaction.fadeInTime) ? fadePct : 1.0f - fadePct );
laction.renderLight.shaderParms[SHADERPARM_GREEN] = fxaction.lightColor.y * ( (fxaction.fadeInTime) ? fadePct : 1.0f - fadePct );
laction.renderLight.shaderParms[SHADERPARM_BLUE] = fxaction.lightColor.z * ( (fxaction.fadeInTime) ? fadePct : 1.0f - fadePct );
gameRenderWorld->UpdateLightDef( laction.lightDefHandle, &laction.renderLight );
}
}
}
/*
================
idEntityFx::Run
================
*/
void idEntityFx::Run( int time ) {
int ieff, j;
idEntity *ent = NULL;
const idDict *projectileDef = NULL;
idProjectile *projectile = NULL;
if ( !fxEffect ) {
return;
}
for( ieff = 0; ieff < fxEffect->events.Num(); ieff++ ) {
const idFXSingleAction& fxaction = fxEffect->events[ieff];
idFXLocalAction& laction = actions[ieff];
//
// if we're currently done with this one
//
if ( laction.start == -1 ) {
continue;
}
//
// see if it's delayed
//
if ( laction.delay ) {
if ( laction.start + (time - laction.start) < laction.start + (laction.delay * 1000) ) {
continue;
}
}
//
// each event can have it's own delay and restart
//
int actualStart = laction.delay ? laction.start + (int)( laction.delay * 1000 ) : laction.start;
float pct = (float)( time - actualStart ) / (1000 * fxaction.duration );
if ( pct >= 1.0f ) {
laction.start = -1;
float totalDelay = 0.0f;
if ( fxaction.restart ) {
if ( fxaction.random1 || fxaction.random2 ) {
totalDelay = fxaction.random1 + gameLocal.random.RandomFloat() * (fxaction.random2 - fxaction.random1);
} else {
totalDelay = fxaction.delay;
}
laction.delay = totalDelay;
laction.start = time;
}
continue;
}
if ( fxaction.fire.Length() ) {
for( j = 0; j < fxEffect->events.Num(); j++ ) {
if ( fxEffect->events[j].name.Icmp( fxaction.fire ) == 0 ) {
actions[j].delay = 0;
}
}
}
idFXLocalAction *useAction;
if ( fxaction.sibling == -1 ) {
useAction = &laction;
} else {
useAction = &actions[fxaction.sibling];
}
assert( useAction );
switch( fxaction.type ) {
case FX_ATTACHLIGHT:
case FX_LIGHT: {
if ( useAction->lightDefHandle == -1 ) {
if ( fxaction.type == FX_LIGHT ) {
memset( &useAction->renderLight, 0, sizeof( renderLight_t ) );
useAction->renderLight.origin = GetPhysics()->GetOrigin() + fxaction.offset;
useAction->renderLight.axis = GetPhysics()->GetAxis();
useAction->renderLight.lightRadius[0] = fxaction.lightRadius;
useAction->renderLight.lightRadius[1] = fxaction.lightRadius;
useAction->renderLight.lightRadius[2] = fxaction.lightRadius;
useAction->renderLight.shader = declManager->FindMaterial( fxaction.data, false );
useAction->renderLight.shaderParms[ SHADERPARM_RED ] = fxaction.lightColor.x;
useAction->renderLight.shaderParms[ SHADERPARM_GREEN ] = fxaction.lightColor.y;
useAction->renderLight.shaderParms[ SHADERPARM_BLUE ] = fxaction.lightColor.z;
useAction->renderLight.shaderParms[ SHADERPARM_TIMESCALE ] = 1.0f;
useAction->renderLight.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( time );
useAction->renderLight.referenceSound = refSound.referenceSound;
useAction->renderLight.pointLight = true;
if ( fxaction.noshadows ) {
useAction->renderLight.noShadows = true;
}
useAction->lightDefHandle = gameRenderWorld->AddLightDef( &useAction->renderLight );
}
if ( fxaction.noshadows ) {
for( j = 0; j < fxEffect->events.Num(); j++ ) {
idFXLocalAction& laction2 = actions[j];
if ( laction2.modelDefHandle != -1 ) {
laction2.renderEntity.noShadow = true;
}
}
}
}
ApplyFade( fxaction, *useAction, time, actualStart );
break;
}
case FX_SOUND: {
if ( !useAction->soundStarted ) {
useAction->soundStarted = true;
const idSoundShader *shader = declManager->FindSound(fxaction.data);
StartSoundShader( shader, SND_CHANNEL_ANY, 0, false, NULL );
for( j = 0; j < fxEffect->events.Num(); j++ ) {
idFXLocalAction& laction2 = actions[j];
if ( laction2.lightDefHandle != -1 ) {
laction2.renderLight.referenceSound = refSound.referenceSound;
gameRenderWorld->UpdateLightDef( laction2.lightDefHandle, &laction2.renderLight );
}
}
}
break;
}
case FX_DECAL: {
if ( !useAction->decalDropped ) {
useAction->decalDropped = true;
gameLocal.ProjectDecal( GetPhysics()->GetOrigin(), GetPhysics()->GetGravity(), 8.0f, true, fxaction.size, fxaction.data );
}
break;
}
case FX_SHAKE: {
if ( !useAction->shakeStarted ) {
idDict args;
args.Clear();
args.SetFloat( "kick_time", fxaction.shakeTime );
args.SetFloat( "kick_amplitude", fxaction.shakeAmplitude );
for ( j = 0; j < gameLocal.numClients; j++ ) {
idPlayer *player = gameLocal.GetClientByNum( j );
if ( player && ( player->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin() ).LengthSqr() < Square( fxaction.shakeDistance ) ) {
if ( !common->IsMultiplayer() || !fxaction.shakeIgnoreMaster || GetBindMaster() != player ) {
player->playerView.DamageImpulse( fxaction.offset, &args );
}
}
}
if ( fxaction.shakeImpulse != 0.0f && fxaction.shakeDistance != 0.0f ) {
idEntity *ignore_ent = NULL;
if ( common->IsMultiplayer() ) {
ignore_ent = this;
if ( fxaction.shakeIgnoreMaster ) {
ignore_ent = GetBindMaster();
}
}
// lookup the ent we are bound to?
gameLocal.RadiusPush( GetPhysics()->GetOrigin(), fxaction.shakeDistance, fxaction.shakeImpulse, this, ignore_ent, 1.0f, true );
}
useAction->shakeStarted = true;
}
break;
}
case FX_ATTACHENTITY:
case FX_PARTICLE:
case FX_MODEL: {
if ( useAction->modelDefHandle == -1 ) {
memset( &useAction->renderEntity, 0, sizeof( renderEntity_t ) );
useAction->renderEntity.origin = GetPhysics()->GetOrigin() + fxaction.offset;
useAction->renderEntity.axis = (fxaction.explicitAxis) ? fxaction.axis : GetPhysics()->GetAxis();
useAction->renderEntity.hModel = renderModelManager->FindModel( fxaction.data );
useAction->renderEntity.shaderParms[ SHADERPARM_RED ] = 1.0f;
useAction->renderEntity.shaderParms[ SHADERPARM_GREEN ] = 1.0f;
useAction->renderEntity.shaderParms[ SHADERPARM_BLUE ] = 1.0f;
useAction->renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( time );
useAction->renderEntity.shaderParms[3] = 1.0f;
useAction->renderEntity.shaderParms[5] = 0.0f;
if ( useAction->renderEntity.hModel ) {
useAction->renderEntity.bounds = useAction->renderEntity.hModel->Bounds( &useAction->renderEntity );
}
useAction->modelDefHandle = gameRenderWorld->AddEntityDef( &useAction->renderEntity );
} else if ( fxaction.trackOrigin ) {
useAction->renderEntity.origin = GetPhysics()->GetOrigin() + fxaction.offset;
useAction->renderEntity.axis = fxaction.explicitAxis ? fxaction.axis : GetPhysics()->GetAxis();
gameRenderWorld->UpdateEntityDef( useAction->modelDefHandle, &useAction->renderEntity );
}
ApplyFade( fxaction, *useAction, time, actualStart );
break;
}
case FX_LAUNCH: {
if ( common->IsClient() ) {
// client never spawns entities outside of ClientReadSnapshot
useAction->launched = true;
break;
}
if ( !useAction->launched ) {
useAction->launched = true;
projectile = NULL;
// FIXME: may need to cache this if it is slow
projectileDef = gameLocal.FindEntityDefDict( fxaction.data, false );
if ( !projectileDef ) {
gameLocal.Warning( "projectile \'%s\' not found", fxaction.data.c_str() );
} else {
gameLocal.SpawnEntityDef( *projectileDef, &ent, false );
if ( ent && ent->IsType( idProjectile::Type ) ) {
projectile = ( idProjectile * )ent;
projectile->Create( this, GetPhysics()->GetOrigin(), GetPhysics()->GetAxis()[0] );
projectile->Launch( GetPhysics()->GetOrigin(), GetPhysics()->GetAxis()[0], vec3_origin );
}
}
}
break;
}
case FX_SHOCKWAVE: {
if ( common->IsClient() ) {
useAction->shakeStarted = true;
break;
}
if ( !useAction->shakeStarted ) {
idStr shockDefName;
useAction->shakeStarted = true;
shockDefName = fxaction.data;
if ( !shockDefName.Length() ) {
shockDefName = "func_shockwave";
}
projectileDef = gameLocal.FindEntityDefDict( shockDefName, false );
if ( !projectileDef ) {
gameLocal.Warning( "shockwave \'%s\' not found", shockDefName.c_str() );
} else {
gameLocal.SpawnEntityDef( *projectileDef, &ent );
ent->SetOrigin( GetPhysics()->GetOrigin() + fxaction.offset );
ent->PostEventMS( &EV_Remove, ent->spawnArgs.GetInt( "duration" ) );
}
}
break;
}
}
}
}
/*
================
idEntityFx::idEntityFx
================
*/
idEntityFx::idEntityFx() {
fxEffect = NULL;
started = -1;
nextTriggerTime = -1;
fl.networkSync = true;
}
/*
================
idEntityFx::~idEntityFx
================
*/
idEntityFx::~idEntityFx() {
CleanUp();
fxEffect = NULL;
}
/*
================
idEntityFx::Spawn
================
*/
void idEntityFx::Spawn() {
if ( g_skipFX.GetBool() ) {
return;
}
const char *fx;
nextTriggerTime = 0;
fxEffect = NULL;
if ( spawnArgs.GetString( "fx", "", &fx ) ) {
systemName = fx;
}
if ( !spawnArgs.GetBool( "triggered" ) ) {
Setup( fx );
if ( spawnArgs.GetBool( "test" ) || spawnArgs.GetBool( "start" ) || spawnArgs.GetFloat ( "restart" ) ) {
PostEventMS( &EV_Activate, 0, this );
}
}
}
/*
================
idEntityFx::Think
Clears any visual fx started when {item,mob,player} was spawned
================
*/
void idEntityFx::Think() {
if ( g_skipFX.GetBool() ) {
return;
}
if ( thinkFlags & TH_THINK ) {
Run( gameLocal.time );
}
RunPhysics();
Present();
}
/*
================
idEntityFx::Event_ClearFx
Clears any visual fx started when item(mob) was spawned
================
*/
void idEntityFx::Event_ClearFx() {
if ( g_skipFX.GetBool() ) {
return;
}
Stop();
CleanUp();
BecomeInactive( TH_THINK );
if ( spawnArgs.GetBool("test") ) {
PostEventMS( &EV_Activate, 0, this );
} else {
if ( spawnArgs.GetFloat( "restart" ) || !spawnArgs.GetBool( "triggered")) {
float rest = spawnArgs.GetFloat( "restart", "0" );
if ( rest == 0.0f ) {
PostEventSec( &EV_Remove, 0.1f );
} else {
rest *= gameLocal.random.RandomFloat();
PostEventSec( &EV_Activate, rest, this );
}
}
}
}
/*
================
idEntityFx::Event_Trigger
================
*/
void idEntityFx::Event_Trigger( idEntity *activator ) {
if ( g_skipFX.GetBool() ) {
return;
}
float fxActionDelay;
const char *fx;
if ( gameLocal.time < nextTriggerTime ) {
return;
}
if ( spawnArgs.GetString( "fx", "", &fx) ) {
Setup( fx );
Start( gameLocal.time );
PostEventMS( &EV_Fx_KillFx, Duration() );
BecomeActive( TH_THINK );
}
fxActionDelay = spawnArgs.GetFloat( "fxActionDelay" );
if ( fxActionDelay != 0.0f ) {
nextTriggerTime = gameLocal.time + SEC2MS( fxActionDelay );
} else {
// prevent multiple triggers on same frame
nextTriggerTime = gameLocal.time + 1;
}
PostEventSec( &EV_Fx_Action, fxActionDelay, activator );
}
/*
================
idEntityFx::StartFx
================
*/
idEntityFx *idEntityFx::StartFx( const char *fx, const idVec3 *useOrigin, const idMat3 *useAxis, idEntity *ent, bool bind ) {
if ( g_skipFX.GetBool() || !fx || !*fx ) {
return NULL;
}
idDict args;
args.SetBool( "start", true );
args.Set( "fx", fx );
idEntityFx *nfx = static_cast<idEntityFx *>( gameLocal.SpawnEntityType( idEntityFx::Type, &args ) );
if ( nfx->Joint() && *nfx->Joint() ) {
nfx->BindToJoint( ent, nfx->Joint(), true );
nfx->SetOrigin( vec3_origin );
} else {
nfx->SetOrigin( (useOrigin) ? *useOrigin : ent->GetPhysics()->GetOrigin() );
nfx->SetAxis( (useAxis) ? *useAxis : ent->GetPhysics()->GetAxis() );
}
if ( bind ) {
// never bind to world spawn
if ( ent != gameLocal.world ) {
nfx->Bind( ent, true );
}
}
nfx->Show();
return nfx;
}
/*
=================
idEntityFx::WriteToSnapshot
=================
*/
void idEntityFx::WriteToSnapshot( idBitMsg &msg ) const {
GetPhysics()->WriteToSnapshot( msg );
WriteBindToSnapshot( msg );
msg.WriteLong( ( fxEffect != NULL ) ? gameLocal.ServerRemapDecl( -1, DECL_FX, fxEffect->Index() ) : -1 );
msg.WriteLong( started );
}
/*
=================
idEntityFx::ReadFromSnapshot
=================
*/
void idEntityFx::ReadFromSnapshot( const idBitMsg &msg ) {
int fx_index, start_time, max_lapse;
GetPhysics()->ReadFromSnapshot( msg );
ReadBindFromSnapshot( msg );
fx_index = gameLocal.ClientRemapDecl( DECL_FX, msg.ReadLong() );
start_time = msg.ReadLong();
if ( fx_index != -1 && start_time > 0 && !fxEffect && started < 0 ) {
spawnArgs.GetInt( "effect_lapse", "1000", max_lapse );
if ( gameLocal.time - start_time > max_lapse ) {
// too late, skip the effect completely
started = 0;
return;
}
const idDeclFX *fx = static_cast<const idDeclFX *>( declManager->DeclByIndex( DECL_FX, fx_index ) );
if ( !fx ) {
gameLocal.Error( "FX at index %d not found", fx_index );
}
fxEffect = fx;
Setup( fx->GetName() );
Start( start_time );
}
}
/*
=================
idEntityFx::ClientThink
=================
*/
void idEntityFx::ClientThink( const int curTime, const float fraction, const bool predict ) {
if ( gameLocal.isNewFrame ) {
Run( gameLocal.serverTime );
}
InterpolatePhysics( fraction );
Present();
}
/*
=================
idEntityFx::ClientPredictionThink
=================
*/
void idEntityFx::ClientPredictionThink() {
if ( gameLocal.isNewFrame ) {
Run( gameLocal.time );
}
RunPhysics();
Present();
}
/*
===============================================================================
idTeleporter
===============================================================================
*/
CLASS_DECLARATION( idEntityFx, idTeleporter )
EVENT( EV_Fx_Action, idTeleporter::Event_DoAction )
END_CLASS
/*
================
idTeleporter::Event_DoAction
================
*/
void idTeleporter::Event_DoAction( idEntity *activator ) {
float angle;
angle = spawnArgs.GetFloat( "angle" );
idAngles a( 0, spawnArgs.GetFloat( "angle" ), 0 );
activator->Teleport( GetPhysics()->GetOrigin(), a, NULL );
}

107
neo/d3xp/Fx.h Normal file
View File

@@ -0,0 +1,107 @@
/*
===========================================================================
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 __GAME_FX_H__
#define __GAME_FX_H__
/*
===============================================================================
Special effects.
===============================================================================
*/
typedef struct {
renderLight_t renderLight; // light presented to the renderer
qhandle_t lightDefHandle; // handle to renderer light def
renderEntity_t renderEntity; // used to present a model to the renderer
int modelDefHandle; // handle to static renderer model
float delay;
int particleSystem;
int start;
bool soundStarted;
bool shakeStarted;
bool decalDropped;
bool launched;
} idFXLocalAction;
class idEntityFx : public idEntity {
public:
CLASS_PROTOTYPE( idEntityFx );
idEntityFx();
virtual ~idEntityFx();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
void Setup( const char *fx );
void Run( int time );
void Start( int time );
void Stop();
const int Duration();
const char * EffectName();
const char * Joint();
const bool Done();
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void ClientPredictionThink();
static idEntityFx * StartFx( const char *fx, const idVec3 *useOrigin, const idMat3 *useAxis, idEntity *ent, bool bind );
protected:
void Event_Trigger( idEntity *activator );
void Event_ClearFx();
void CleanUp();
void CleanUpSingleAction( const idFXSingleAction& fxaction, idFXLocalAction& laction );
void ApplyFade( const idFXSingleAction& fxaction, idFXLocalAction& laction, const int time, const int actualStart );
int started;
int nextTriggerTime;
const idDeclFX * fxEffect; // GetFX() should be called before using fxEffect as a pointer
idList<idFXLocalAction, TAG_FX> actions;
idStr systemName;
};
class idTeleporter : public idEntityFx {
public:
CLASS_PROTOTYPE( idTeleporter );
private:
// teleporters to this location
void Event_DoAction( idEntity *activator );
};
#endif /* !__GAME_FX_H__ */

2
neo/d3xp/Game.def Normal file
View File

@@ -0,0 +1,2 @@
EXPORTS
GetGameAPI

343
neo/d3xp/Game.h Normal file
View File

@@ -0,0 +1,343 @@
/*
===========================================================================
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 __GAME_H__
#define __GAME_H__
/*
===============================================================================
Public game interface with methods to run the game.
===============================================================================
*/
// default scripts
#define SCRIPT_DEFAULTDEFS "script/doom_defs.script"
#define SCRIPT_DEFAULT "script/doom_main.script"
#define SCRIPT_DEFAULTFUNC "doom_main"
struct gameReturn_t {
gameReturn_t() :
syncNextGameFrame( false ),
vibrationLow( 0 ),
vibrationHigh( 0 ) {
}
char sessionCommand[MAX_STRING_CHARS]; // "map", "disconnect", "victory", etc
bool syncNextGameFrame; // used when cinematics are skipped to prevent session from simulating several game frames to
// keep the game time in sync with real time
int vibrationLow;
int vibrationHigh;
};
#define TIME_GROUP1 0
#define TIME_GROUP2 1
class idGame {
public:
virtual ~idGame() {}
// Initialize the game for the first time.
virtual void Init() = 0;
// Shut down the entire game.
virtual void Shutdown() = 0;
// Sets the serverinfo at map loads and when it changes.
virtual void SetServerInfo( const idDict &serverInfo ) = 0;
// Gets the serverinfo, common calls this before saving the game
virtual const idDict & GetServerInfo() = 0;
// Interpolated server time
virtual void SetServerGameTimeMs( const int time ) = 0;
// Interpolated server time
virtual int GetServerGameTimeMs() const = 0;
virtual int GetSSEndTime() const = 0;
virtual int GetSSStartTime() const = 0;
// common calls this before moving the single player game to a new level.
virtual const idDict & GetPersistentPlayerInfo( int clientNum ) = 0;
// common calls this right before a new level is loaded.
virtual void SetPersistentPlayerInfo( int clientNum, const idDict &playerInfo ) = 0;
// Loads a map and spawns all the entities.
virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, int gameMode, int randseed ) = 0;
// Loads a map from a savegame file.
virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile, idFile *stringTableFile, int saveGameVersion ) = 0;
// Saves the current game state, common may have written some data to the file already.
virtual void SaveGame( idFile *saveGameFile, idFile *stringTableFile ) = 0;
// Pulls the current player location from the game information
virtual void GetSaveGameDetails( idSaveGameDetails & gameDetails ) = 0;
// Shut down the current map.
virtual void MapShutdown() = 0;
// Caches media referenced from in key/value pairs in the given dictionary.
virtual void CacheDictionaryMedia( const idDict *dict ) = 0;
virtual void Preload( const idPreloadManifest &manifest ) = 0;
// Runs a game frame, may return a session command for level changing, etc
virtual void RunFrame( idUserCmdMgr & cmdMgr, gameReturn_t & gameReturn ) = 0;
// Makes rendering and sound system calls to display for a given clientNum.
virtual bool Draw( int clientNum ) = 0;
virtual bool HandlePlayerGuiEvent( const sysEvent_t * ev ) = 0;
// Writes a snapshot of the server game state.
virtual void ServerWriteSnapshot( idSnapShot & ss ) = 0;
// Processes a reliable message
virtual void ProcessReliableMessage( int clientNum, int type, const idBitMsg &msg ) = 0;
virtual void SetInterpolation( const float fraction, const int serverGameMS, const int ssStartTime, const int ssEndTime ) = 0;
// Reads a snapshot and updates the client game state.
virtual void ClientReadSnapshot( const idSnapShot & ss ) = 0;
// Runs prediction on entities at the client.
virtual void ClientRunFrame( idUserCmdMgr & cmdMgr, bool lastPredictFrame, gameReturn_t & ret ) = 0;
// Used to manage divergent time-lines
virtual int GetTimeGroupTime( int timeGroup ) = 0;
// Returns a list of available multiplayer game modes
virtual int GetMPGameModes( const char *** gameModes, const char *** gameModesDisplay ) = 0;
// Returns a summary of stats for a given client
virtual void GetClientStats( int clientNum, char *data, const int len ) = 0;
virtual bool IsInGame() const = 0;
// Get the player entity number for a network peer.
virtual int MapPeerToClient( int peer ) const = 0;
// Get the player entity number of the local player.
virtual int GetLocalClientNum() const = 0;
// compute an angle offset to be applied to the given client's aim
virtual void GetAimAssistAngles( idAngles & angles ) = 0;
virtual float GetAimAssistSensitivity() = 0;
// Release the mouse when the PDA is open
virtual bool IsPDAOpen() const = 0;
virtual bool IsPlayerChatting() const = 0;
// Creates leaderboards for each map/mode defined.
virtual void Leaderboards_Init() = 0;
virtual void Leaderboards_Shutdown() = 0;
// MAIN MENU FUNCTIONS
virtual bool InhibitControls() = 0;
virtual void Shell_Init( const char * filename, idSoundWorld * sw ) = 0;
virtual void Shell_Cleanup() = 0;
virtual void Shell_CreateMenu( bool inGame ) = 0;
virtual void Shell_ClosePause() = 0;
virtual void Shell_Show( bool show ) = 0;
virtual bool Shell_IsActive() const = 0;
virtual bool Shell_HandleGuiEvent( const sysEvent_t * sev ) = 0;
virtual void Shell_Render() = 0;
virtual void Shell_ResetMenu() = 0;
virtual void Shell_SyncWithSession() = 0;
virtual void Shell_UpdateSavedGames() = 0;
virtual void Shell_SetCanContinue( bool valid ) = 0;
virtual void Shell_UpdateClientCountdown( int countdown ) = 0;
virtual void Shell_UpdateLeaderboard( const idLeaderboardCallback * callback ) = 0;
virtual void Shell_SetGameComplete() = 0;
};
extern idGame * game;
/*
===============================================================================
Public game interface with methods for in-game editing.
===============================================================================
*/
typedef struct {
idSoundEmitter * referenceSound; // this is the interface to the sound system, created
// with idSoundWorld::AllocSoundEmitter() when needed
idVec3 origin;
int listenerId; // SSF_PRIVATE_SOUND only plays if == listenerId from PlaceListener
// no spatialization will be performed if == listenerID
const idSoundShader * shader; // this really shouldn't be here, it is a holdover from single channel behavior
float diversity; // 0.0 to 1.0 value used to select which
// samples in a multi-sample list from the shader are used
bool waitfortrigger; // don't start it at spawn time
soundShaderParms_t parms; // override volume, flags, etc
} refSound_t;
enum {
TEST_PARTICLE_MODEL = 0,
TEST_PARTICLE_IMPACT,
TEST_PARTICLE_MUZZLE,
TEST_PARTICLE_FLIGHT,
TEST_PARTICLE_SELECTED
};
class idEntity;
class idMD5Anim;
// FIXME: this interface needs to be reworked but it properly separates code for the time being
class idGameEdit {
public:
virtual ~idGameEdit() {}
// These are the canonical idDict to parameter parsing routines used by both the game and tools.
virtual void ParseSpawnArgsToRenderLight( const idDict *args, renderLight_t *renderLight );
virtual void ParseSpawnArgsToRenderEntity( const idDict *args, renderEntity_t *renderEntity );
virtual void ParseSpawnArgsToRefSound( const idDict *args, refSound_t *refSound );
// Animation system calls for non-game based skeletal rendering.
virtual idRenderModel * ANIM_GetModelFromEntityDef( const char *classname );
virtual const idVec3 &ANIM_GetModelOffsetFromEntityDef( const char *classname );
virtual idRenderModel * ANIM_GetModelFromEntityDef( const idDict *args );
virtual idRenderModel * ANIM_GetModelFromName( const char *modelName );
virtual const idMD5Anim * ANIM_GetAnimFromEntityDef( const char *classname, const char *animname );
virtual int ANIM_GetNumAnimsFromEntityDef( const idDict *args );
virtual const char * ANIM_GetAnimNameFromEntityDef( const idDict *args, int animNum );
virtual const idMD5Anim * ANIM_GetAnim( const char *fileName );
virtual int ANIM_GetLength( const idMD5Anim *anim );
virtual int ANIM_GetNumFrames( const idMD5Anim *anim );
virtual void ANIM_CreateAnimFrame( const idRenderModel *model, const idMD5Anim *anim, int numJoints, idJointMat *frame, int time, const idVec3 &offset, bool remove_origin_offset );
virtual idRenderModel * ANIM_CreateMeshForAnim( idRenderModel *model, const char *classname, const char *animname, int frame, bool remove_origin_offset );
// Articulated Figure calls for AF editor and Radiant.
virtual bool AF_SpawnEntity( const char *fileName );
virtual void AF_UpdateEntities( const char *fileName );
virtual void AF_UndoChanges();
virtual idRenderModel * AF_CreateMesh( const idDict &args, idVec3 &meshOrigin, idMat3 &meshAxis, bool &poseIsSet );
// Entity selection.
virtual void ClearEntitySelection();
virtual int GetSelectedEntities( idEntity *list[], int max );
virtual void AddSelectedEntity( idEntity *ent );
// Selection methods
virtual void TriggerSelected();
// Entity defs and spawning.
virtual const idDict * FindEntityDefDict( const char *name, bool makeDefault = true ) const;
virtual void SpawnEntityDef( const idDict &args, idEntity **ent );
virtual idEntity * FindEntity( const char *name ) const;
virtual const char * GetUniqueEntityName( const char *classname ) const;
// Entity methods.
virtual void EntityGetOrigin( idEntity *ent, idVec3 &org ) const;
virtual void EntityGetAxis( idEntity *ent, idMat3 &axis ) const;
virtual void EntitySetOrigin( idEntity *ent, const idVec3 &org );
virtual void EntitySetAxis( idEntity *ent, const idMat3 &axis );
virtual void EntityTranslate( idEntity *ent, const idVec3 &org );
virtual const idDict * EntityGetSpawnArgs( idEntity *ent ) const;
virtual void EntityUpdateChangeableSpawnArgs( idEntity *ent, const idDict *dict );
virtual void EntityChangeSpawnArgs( idEntity *ent, const idDict *newArgs );
virtual void EntityUpdateVisuals( idEntity *ent );
virtual void EntitySetModel( idEntity *ent, const char *val );
virtual void EntityStopSound( idEntity *ent );
virtual void EntityDelete( idEntity *ent );
virtual void EntitySetColor( idEntity *ent, const idVec3 color );
// Player methods.
virtual bool PlayerIsValid() const;
virtual void PlayerGetOrigin( idVec3 &org ) const;
virtual void PlayerGetAxis( idMat3 &axis ) const;
virtual void PlayerGetViewAngles( idAngles &angles ) const;
virtual void PlayerGetEyePosition( idVec3 &org ) const;
// In game map editing support.
virtual const idDict * MapGetEntityDict( const char *name ) const;
virtual void MapSave( const char *path = NULL ) const;
virtual void MapSetEntityKeyVal( const char *name, const char *key, const char *val ) const ;
virtual void MapCopyDictToEntity( const char *name, const idDict *dict ) const;
virtual int MapGetUniqueMatchingKeyVals( const char *key, const char *list[], const int max ) const;
virtual void MapAddEntity( const idDict *dict ) const;
virtual int MapGetEntitiesMatchingClassWithString( const char *classname, const char *match, const char *list[], const int max ) const;
virtual void MapRemoveEntity( const char *name ) const;
virtual void MapEntityTranslate( const char *name, const idVec3 &v ) const;
};
extern idGameEdit * gameEdit;
/*
===============================================================================
Game API.
===============================================================================
*/
const int GAME_API_VERSION = 8;
typedef struct {
int version; // API version
idSys * sys; // non-portable system services
idCommon * common; // common
idCmdSystem * cmdSystem; // console command system
idCVarSystem * cvarSystem; // console variable system
idFileSystem * fileSystem; // file system
idRenderSystem * renderSystem; // render system
idSoundSystem * soundSystem; // sound system
idRenderModelManager * renderModelManager; // render model manager
idUserInterfaceManager * uiManager; // user interface manager
idDeclManager * declManager; // declaration manager
idAASFileManager * AASFileManager; // AAS file manager
idCollisionModelManager * collisionModelManager; // collision model manager
} gameImport_t;
typedef struct {
int version; // API version
idGame * game; // interface to run the game
idGameEdit * gameEdit; // interface for in-game editing
} gameExport_t;
extern "C" {
typedef gameExport_t * (*GetGameAPI_t)( gameImport_t *import );
}
#endif /* !__GAME_H__ */

1142
neo/d3xp/GameEdit.cpp Normal file

File diff suppressed because it is too large Load Diff

119
neo/d3xp/GameEdit.h Normal file
View File

@@ -0,0 +1,119 @@
/*
===========================================================================
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 __GAME_EDIT_H__
#define __GAME_EDIT_H__
/*
===============================================================================
Ingame cursor.
===============================================================================
*/
class idCursor3D : public idEntity {
public:
CLASS_PROTOTYPE( idCursor3D );
idCursor3D();
~idCursor3D();
void Spawn();
void Present();
void Think();
idForce_Drag drag;
idVec3 draggedPosition;
};
/*
===============================================================================
Allows entities to be dragged through the world with physics.
===============================================================================
*/
class idDragEntity {
public:
idDragEntity();
~idDragEntity();
void Clear();
void Update( idPlayer *player );
void SetSelected( idEntity *ent );
idEntity * GetSelected() const { return selected.GetEntity(); }
void DeleteSelected();
void BindSelected();
void UnbindSelected();
private:
idEntityPtr<idEntity> dragEnt; // entity being dragged
jointHandle_t joint; // joint being dragged
int id; // id of body being dragged
idVec3 localEntityPoint; // dragged point in entity space
idVec3 localPlayerPoint; // dragged point in player space
idStr bodyName; // name of the body being dragged
idCursor3D * cursor; // cursor entity
idEntityPtr<idEntity> selected; // last dragged entity
void StopDrag();
};
/*
===============================================================================
Handles ingame entity editing.
===============================================================================
*/
typedef struct selectedTypeInfo_s {
idTypeInfo *typeInfo;
idStr textKey;
} selectedTypeInfo_t;
class idEditEntities {
public:
idEditEntities();
bool SelectEntity( const idVec3 &origin, const idVec3 &dir, const idEntity *skip );
void AddSelectedEntity( idEntity *ent );
void RemoveSelectedEntity( idEntity *ent );
void ClearSelectedEntities();
void DisplayEntities();
bool EntityIsSelectable( idEntity *ent, idVec4 *color = NULL, idStr *text = NULL );
private:
int nextSelectTime;
idList<selectedTypeInfo_t> selectableEntityClasses;
idList<idEntity *> selectedEntities;
};
#endif /* !__GAME_EDIT_H__ */

5085
neo/d3xp/Game_local.cpp Normal file

File diff suppressed because it is too large Load Diff

819
neo/d3xp/Game_local.h Normal file
View File

@@ -0,0 +1,819 @@
/*
===========================================================================
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 __GAME_LOCAL_H__
#define __GAME_LOCAL_H__
/*
===============================================================================
Local implementation of the public game interface.
===============================================================================
*/
#ifdef ID_DEBUG_UNINITIALIZED_MEMORY
// This is real evil but allows the code to inspect arbitrary class variables.
#define private public
#define protected public
#endif
extern idRenderWorld * gameRenderWorld;
extern idSoundWorld * gameSoundWorld;
// the "gameversion" client command will print this plus compile date
#define GAME_VERSION "baseDOOM-1"
// classes used by idGameLocal
class idEntity;
class idActor;
class idPlayer;
class idCamera;
class idWorldspawn;
class idTestModel;
class idAAS;
class idAI;
class idSmokeParticles;
class idEntityFx;
class idTypeInfo;
class idProgram;
class idThread;
class idEditEntities;
class idLocationEntity;
class idMenuHandler_Shell;
const int MAX_CLIENTS = MAX_PLAYERS;
const int MAX_CLIENTS_IN_PVS = MAX_CLIENTS >> 3;
const int GENTITYNUM_BITS = 12;
const int MAX_GENTITIES = 1 << GENTITYNUM_BITS;
const int ENTITYNUM_NONE = MAX_GENTITIES - 1;
const int ENTITYNUM_WORLD = MAX_GENTITIES - 2;
const int ENTITYNUM_MAX_NORMAL = MAX_GENTITIES - 2;
const int ENTITYNUM_FIRST_NON_REPLICATED = ENTITYNUM_MAX_NORMAL - 256;
//============================================================================
void gameError( const char *fmt, ... );
#include "gamesys/Event.h"
#include "gamesys/Class.h"
#include "gamesys/SysCvar.h"
#include "gamesys/SysCmds.h"
#include "gamesys/SaveGame.h"
#include "script/Script_Program.h"
#include "anim/Anim.h"
#include "ai/AAS.h"
#include "physics/Clip.h"
#include "physics/Push.h"
#include "Pvs.h"
#include "Leaderboards.h"
#include "MultiplayerGame.h"
class idWeapon;
//============================================================================
const int MAX_GAME_MESSAGE_SIZE = 8192;
const int MAX_ENTITY_STATE_SIZE = 512;
const int ENTITY_PVS_SIZE = ((MAX_GENTITIES+31)>>5);
const int NUM_RENDER_PORTAL_BITS = idMath::BitsForInteger( PS_BLOCK_ALL );
const int MAX_EVENT_PARAM_SIZE = 128;
typedef struct entityNetEvent_s {
int spawnId;
int event;
int time;
int paramsSize;
byte paramsBuf[MAX_EVENT_PARAM_SIZE];
struct entityNetEvent_s *next;
struct entityNetEvent_s *prev;
} entityNetEvent_t;
enum {
GAME_RELIABLE_MESSAGE_SYNCEDCVARS,
GAME_RELIABLE_MESSAGE_SPAWN_PLAYER,
GAME_RELIABLE_MESSAGE_CHAT,
GAME_RELIABLE_MESSAGE_TCHAT,
GAME_RELIABLE_MESSAGE_SOUND_EVENT,
GAME_RELIABLE_MESSAGE_SOUND_INDEX,
GAME_RELIABLE_MESSAGE_DB,
GAME_RELIABLE_MESSAGE_DROPWEAPON,
GAME_RELIABLE_MESSAGE_RESTART,
GAME_RELIABLE_MESSAGE_TOURNEYLINE,
GAME_RELIABLE_MESSAGE_VCHAT,
GAME_RELIABLE_MESSAGE_STARTSTATE,
GAME_RELIABLE_MESSAGE_WARMUPTIME,
GAME_RELIABLE_MESSAGE_SPECTATE,
GAME_RELIABLE_MESSAGE_EVENT,
GAME_RELIABLE_MESSAGE_LOBBY_COUNTDOWN,
GAME_RELIABLE_MESSAGE_RESPAWN_AVAILABLE, // Used just to show clients the respawn text on the hud.
GAME_RELIABLE_MESSAGE_MATCH_STARTED_TIME,
GAME_RELIABLE_MESSAGE_ACHIEVEMENT_UNLOCK,
GAME_RELIABLE_MESSAGE_CLIENT_HITSCAN_HIT
};
typedef enum {
GAMESTATE_UNINITIALIZED, // prior to Init being called
GAMESTATE_NOMAP, // no map loaded
GAMESTATE_STARTUP, // inside InitFromNewMap(). spawning map entities.
GAMESTATE_ACTIVE, // normal gameplay
GAMESTATE_SHUTDOWN // inside MapShutdown(). clearing memory.
} gameState_t;
typedef struct {
idEntity *ent;
int dist;
int team;
} spawnSpot_t;
//============================================================================
class idEventQueue {
public:
typedef enum {
OUTOFORDER_IGNORE,
OUTOFORDER_DROP,
OUTOFORDER_SORT
} outOfOrderBehaviour_t;
idEventQueue() : start( NULL ), end( NULL ) {}
entityNetEvent_t * Alloc();
void Free( entityNetEvent_t *event );
void Shutdown();
void Init();
void Enqueue( entityNetEvent_t* event, outOfOrderBehaviour_t oooBehaviour );
entityNetEvent_t * Dequeue();
entityNetEvent_t * RemoveLast();
entityNetEvent_t * Start() { return start; }
private:
entityNetEvent_t * start;
entityNetEvent_t * end;
idBlockAlloc<entityNetEvent_t,32> eventAllocator;
};
//============================================================================
template< class type >
class idEntityPtr {
public:
idEntityPtr();
// save games
void Save( idSaveGame *savefile ) const; // archives object for save game file
void Restore( idRestoreGame *savefile ); // unarchives object from save game file
idEntityPtr & operator=( const type * ent );
idEntityPtr & operator=( const idEntityPtr & ep );
bool operator==( const idEntityPtr & ep ) { return spawnId == ep.spawnId; }
type * operator->() const { return GetEntity(); }
operator type * () const { return GetEntity(); }
// synchronize entity pointers over the network
int GetSpawnId() const { return spawnId; }
bool SetSpawnId( int id );
bool UpdateSpawnId();
bool IsValid() const;
type * GetEntity() const;
int GetEntityNum() const;
private:
int spawnId;
};
struct timeState_t {
int time;
int previousTime;
int realClientTime;
void Set( int t, int pt, int rct ) { time = t; previousTime = pt; realClientTime = rct; };
void Get( int & t, int & pt, int & rct ) { t = time; pt = previousTime; rct = realClientTime; };
void Save( idSaveGame *savefile ) const { savefile->WriteInt( time ); savefile->WriteInt( previousTime ); savefile->WriteInt( realClientTime ); }
void Restore( idRestoreGame *savefile ) { savefile->ReadInt( time ); savefile->ReadInt( previousTime ); savefile->ReadInt( realClientTime ); }
};
enum slowmoState_t {
SLOWMO_STATE_OFF,
SLOWMO_STATE_RAMPUP,
SLOWMO_STATE_ON,
SLOWMO_STATE_RAMPDOWN
};
//============================================================================
class idGameLocal : public idGame {
public:
int previousServerTime; // time in msec of last frame on the server
int serverTime; // in msec. ( on the client ) the server time. ( on the server ) the actual game time.
idDict serverInfo; // all the tunable parameters, like numclients, etc
int numClients; // pulled from serverInfo and verified
idArray< lobbyUserID_t, MAX_CLIENTS > lobbyUserIDs; // Maps from a client (player) number to a lobby user
idDict persistentPlayerInfo[MAX_CLIENTS];
idEntity * entities[MAX_GENTITIES];// index to entities
int spawnIds[MAX_GENTITIES];// for use in idEntityPtr
idArray< int, 2 > firstFreeEntityIndex; // first free index in the entities array. [0] for replicated entities, [1] for non-replicated
int num_entities; // current number <= MAX_GENTITIES
idHashIndex entityHash; // hash table to quickly find entities by name
idWorldspawn * world; // world entity
idLinkList<idEntity> spawnedEntities; // all spawned entities
idLinkList<idEntity> activeEntities; // all thinking entities (idEntity::thinkFlags != 0)
idLinkList<idEntity> aimAssistEntities; // all aim Assist entities
int numEntitiesToDeactivate;// number of entities that became inactive in current frame
bool sortPushers; // true if active lists needs to be reordered to place pushers at the front
bool sortTeamMasters; // true if active lists needs to be reordered to place physics team masters before their slaves
idDict persistentLevelInfo; // contains args that are kept around between levels
// can be used to automatically effect every material in the world that references globalParms
float globalShaderParms[ MAX_GLOBAL_SHADER_PARMS ];
idRandom random; // random number generator used throughout the game
idProgram program; // currently loaded script and data space
idThread * frameCommandThread;
idClip clip; // collision detection
idPush push; // geometric pushing
idPVS pvs; // potential visible set
idTestModel * testmodel; // for development testing of models
idEntityFx * testFx; // for development testing of fx
idStr sessionCommand; // a target_sessionCommand can set this to return something to the session
idMultiplayerGame mpGame; // handles rules for standard dm
idSmokeParticles * smokeParticles; // global smoke trails
idEditEntities * editEntities; // in game editing
bool inCinematic; // game is playing cinematic (player controls frozen)
int framenum;
int time; // in msec
int previousTime; // time in msec of last frame
int vacuumAreaNum; // -1 if level doesn't have any outside areas
gameType_t gameType;
idLinkList<idEntity> snapshotEntities; // entities from the last snapshot
int realClientTime; // real client time
bool isNewFrame; // true if this is a new game frame, not a rerun due to prediction
float clientSmoothing; // smoothing of other clients in the view
int entityDefBits; // bits required to store an entity def number
static const char * sufaceTypeNames[ MAX_SURFACE_TYPES ]; // text names for surface types
idEntityPtr<idEntity> lastGUIEnt; // last entity with a GUI, used by Cmd_NextGUI_f
int lastGUI; // last GUI on the lastGUIEnt
idEntityPtr<idPlayer> playerActivateFragChamber; // The player that activated the frag chamber
idEntityPtr<idEntity> portalSkyEnt;
bool portalSkyActive;
void SetPortalSkyEnt( idEntity *ent );
bool IsPortalSkyAcive();
timeState_t fast;
timeState_t slow;
int selectedGroup;
slowmoState_t slowmoState;
float slowmoScale;
bool quickSlowmoReset;
virtual void SelectTimeGroup( int timeGroup );
virtual int GetTimeGroupTime( int timeGroup );
void ComputeSlowScale();
void RunTimeGroup2( idUserCmdMgr & userCmdMgr );
void ResetSlowTimeVars();
void QuickSlowmoReset();
void Tokenize( idStrList &out, const char *in );
// ---------------------- Public idGame Interface -------------------
idGameLocal();
virtual void Init();
virtual void Shutdown();
virtual void SetServerInfo( const idDict &serverInfo );
virtual const idDict & GetServerInfo();
virtual const idDict & GetPersistentPlayerInfo( int clientNum );
virtual void SetPersistentPlayerInfo( int clientNum, const idDict &playerInfo );
virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, int gameType, int randSeed );
virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile * saveGameFile, idFile * stringTableFile, int saveGameVersion );
virtual void SaveGame( idFile *saveGameFile, idFile *stringTableFile );
virtual void GetSaveGameDetails( idSaveGameDetails & gameDetails );
virtual void MapShutdown();
virtual void CacheDictionaryMedia( const idDict *dict );
virtual void Preload( const idPreloadManifest &manifest );
virtual void RunFrame( idUserCmdMgr & cmdMgr, gameReturn_t & gameReturn );
void RunAllUserCmdsForPlayer( idUserCmdMgr & cmdMgr, const int playerNumber );
void RunSingleUserCmd( usercmd_t & cmd, idPlayer & player );
void RunEntityThink( idEntity & ent, idUserCmdMgr & userCmdMgr );
virtual bool Draw( int clientNum );
virtual bool HandlePlayerGuiEvent( const sysEvent_t * ev );
virtual void ServerWriteSnapshot( idSnapShot & ss );
virtual void ProcessReliableMessage( int clientNum, int type, const idBitMsg &msg );
virtual void ClientReadSnapshot( const idSnapShot & ss );
virtual void ClientRunFrame( idUserCmdMgr & cmdMgr, bool lastPredictFrame, gameReturn_t & ret );
void BuildReturnValue( gameReturn_t & ret );
virtual int GetMPGameModes( const char *** gameModes, const char *** gameModesDisplay );
virtual void GetClientStats( int clientNum, char *data, const int len );
virtual bool IsInGame() const { return GameState() == GAMESTATE_ACTIVE; }
virtual int MapPeerToClient( int peer ) const;
virtual int GetLocalClientNum() const;
virtual void GetAimAssistAngles( idAngles & angles );
virtual float GetAimAssistSensitivity();
// ---------------------- Public idGameLocal Interface -------------------
void Printf( VERIFY_FORMAT_STRING const char *fmt, ... ) const;
void DPrintf( VERIFY_FORMAT_STRING const char *fmt, ... ) const;
void Warning( VERIFY_FORMAT_STRING const char *fmt, ... ) const;
void DWarning( VERIFY_FORMAT_STRING const char *fmt, ... ) const;
void Error( VERIFY_FORMAT_STRING const char *fmt, ... ) const;
// Initializes all map variables common to both save games and spawned games
void LoadMap( const char *mapName, int randseed );
void LocalMapRestart();
void MapRestart();
static void MapRestart_f( const idCmdArgs &args );
idMapFile * GetLevelMap();
const char * GetMapName() const;
int NumAAS() const;
idAAS * GetAAS( int num ) const;
idAAS * GetAAS( const char *name ) const;
void SetAASAreaState( const idBounds &bounds, const int areaContents, bool closed );
aasHandle_t AddAASObstacle( const idBounds &bounds );
void RemoveAASObstacle( const aasHandle_t handle );
void RemoveAllAASObstacles();
bool CheatsOk( bool requirePlayer = true );
gameState_t GameState() const;
idEntity * SpawnEntityType( const idTypeInfo &classdef, const idDict *args = NULL, bool bIsClientReadSnapshot = false );
bool SpawnEntityDef( const idDict &args, idEntity **ent = NULL, bool setDefaults = true );
int GetSpawnId( const idEntity *ent ) const;
const idDeclEntityDef * FindEntityDef( const char *name, bool makeDefault = true ) const;
const idDict * FindEntityDefDict( const char *name, bool makeDefault = true ) const;
void RegisterEntity( idEntity *ent, int forceSpawnId, const idDict & spawnArgsToCopy );
void UnregisterEntity( idEntity *ent );
const idDict & GetSpawnArgs() const { return spawnArgs; }
bool RequirementMet( idEntity *activator, const idStr &requires, int removeItem );
void AlertAI( idEntity *ent );
idActor * GetAlertEntity();
bool InPlayerPVS( idEntity *ent ) const;
bool InPlayerConnectedArea( idEntity *ent ) const;
pvsHandle_t GetPlayerPVS() { return playerPVS; };
void SetCamera( idCamera *cam );
idCamera * GetCamera() const;
void CalcFov( float base_fov, float &fov_x, float &fov_y ) const;
void AddEntityToHash( const char *name, idEntity *ent );
bool RemoveEntityFromHash( const char *name, idEntity *ent );
int GetTargets( const idDict &args, idList< idEntityPtr<idEntity> > &list, const char *ref ) const;
// returns the master entity of a trace. for example, if the trace entity is the player's head, it will return the player.
idEntity * GetTraceEntity( const trace_t &trace ) const;
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;
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 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 );
void BloodSplat( const idVec3 &origin, const idVec3 &dir, float size, const char *material );
void CallFrameCommand( idEntity *ent, const function_t *frameCommand );
void CallObjectFrameCommand( idEntity *ent, const char *frameCommand );
const idVec3 & GetGravity() const;
// added the following to assist licensees with merge issues
int GetFrameNum() const { return framenum; };
int GetTime() const { return time; };
int GetNextClientNum( int current ) const;
idPlayer * GetClientByNum( int current ) const;
idPlayer * GetLocalPlayer() const;
void SpreadLocations();
idLocationEntity * LocationForPoint( const idVec3 &point ); // May return NULL
idEntity * SelectInitialSpawnPoint( idPlayer *player );
void SetPortalState( qhandle_t portal, int blockingBits );
void SaveEntityNetworkEvent( const idEntity *ent, int event, const idBitMsg *msg );
int ServerRemapDecl( int clientNum, declType_t type, int index );
int ClientRemapDecl( declType_t type, int index );
void SyncPlayersWithLobbyUsers( bool initial );
void ServerWriteInitialReliableMessages( int clientNum, lobbyUserID_t lobbyUserID );
void ServerSendNetworkSyncCvars();
virtual void SetInterpolation( const float fraction, const int serverGameMS, const int ssStartTime, const int ssEndTime );
void ServerProcessReliableMessage( int clientNum, int type, const idBitMsg &msg );
void ClientProcessReliableMessage( int type, const idBitMsg &msg );
// Snapshot times - track exactly what times we are interpolating from and to
int GetSSEndTime() const { return netInterpolationInfo.ssEndTime; }
int GetSSStartTime() const { return netInterpolationInfo.ssStartTime; }
virtual void SetServerGameTimeMs( const int time );
virtual int GetServerGameTimeMs() const;
idEntity * FindPredictedEntity( uint32 predictedKey, idTypeInfo * type );
uint32 GeneratePredictionKey( idWeapon * weapon, idPlayer * playerAttacker, int overrideKey );
int GetLastClientUsercmdMilliseconds( int playerIndex ) const { return usercmdLastClientMilliseconds[ playerIndex ]; }
void SetGlobalMaterial( const idMaterial *mat );
const idMaterial * GetGlobalMaterial();
void SetGibTime( int _time ) { nextGibTime = _time; };
int GetGibTime() { return nextGibTime; };
virtual bool InhibitControls();
virtual bool IsPDAOpen() const;
virtual bool IsPlayerChatting() const;
// Creates leaderboards for each map/mode defined.
virtual void Leaderboards_Init();
virtual void Leaderboards_Shutdown();
// MAIN MENU FUNCTIONS
virtual void Shell_Init( const char * filename, idSoundWorld * sw );
virtual void Shell_Cleanup();
virtual void Shell_Show( bool show );
virtual void Shell_ClosePause();
virtual void Shell_CreateMenu( bool inGame );
virtual bool Shell_IsActive() const;
virtual bool Shell_HandleGuiEvent( const sysEvent_t * sev );
virtual void Shell_Render();
virtual void Shell_ResetMenu();
virtual void Shell_SyncWithSession() ;
virtual void Shell_SetCanContinue( bool valid );
virtual void Shell_UpdateSavedGames();
virtual void Shell_UpdateClientCountdown( int countdown );
virtual void Shell_UpdateLeaderboard( const idLeaderboardCallback * callback );
virtual void Shell_SetGameComplete();
void Shell_ClearRepeater();
const char * GetMapFileName() { return mapFileName.c_str(); }
const char * GetMPPlayerDefName() const;
private:
const static int INITIAL_SPAWN_COUNT = 1;
idStr mapFileName; // name of the map, empty string if no map loaded
idMapFile * mapFile; // will be NULL during the game unless in-game editing is used
bool mapCycleLoaded;
int spawnCount;
int mapSpawnCount; // it's handy to know which entities are part of the map
idLocationEntity ** locationEntities; // for location names, etc
idCamera * camera;
const idMaterial * globalMaterial; // for overriding everything
idList<idAAS *> aasList; // area system
idMenuHandler_Shell * shellHandler;
idStrList aasNames;
idEntityPtr<idActor> lastAIAlertEntity;
int lastAIAlertTime;
idDict spawnArgs; // spawn args used during entity spawning FIXME: shouldn't be necessary anymore
pvsHandle_t playerPVS; // merged pvs of all players
pvsHandle_t playerConnectedAreas; // all areas connected to any player area
idVec3 gravity; // global gravity vector
gameState_t gamestate; // keeps track of whether we're spawning, shutting down, or normal gameplay
bool influenceActive; // true when a phantasm is happening
int nextGibTime;
idEventQueue eventQueue;
idEventQueue savedEventQueue;
idStaticList<spawnSpot_t, MAX_GENTITIES> spawnSpots;
idStaticList<idEntity *, MAX_GENTITIES> initialSpots;
int currentInitialSpot;
idStaticList<spawnSpot_t, MAX_GENTITIES> teamSpawnSpots[2];
idStaticList<idEntity *, MAX_GENTITIES> teamInitialSpots[2];
int teamCurrentInitialSpot[2];
struct netInterpolationInfo_t { // Was in GameTimeManager.h in id5, needed common place to put this.
netInterpolationInfo_t()
: pct( 0.0f )
, serverGameMs( 0 )
, previousServerGameMs( 0 )
, ssStartTime( 0 )
, ssEndTime( 0 )
{}
float pct; // % of current interpolation
int serverGameMs; // Interpolated server game time
int previousServerGameMs; // last frame's interpolated server game time
int ssStartTime; // Server time of old snapshot
int ssEndTime; // Server time of next snapshot
};
netInterpolationInfo_t netInterpolationInfo;
idDict newInfo;
idArray< int, MAX_PLAYERS > usercmdLastClientMilliseconds; // The latest client time the server has run.
idArray< int, MAX_PLAYERS > lastCmdRunTimeOnClient;
idArray< int, MAX_PLAYERS > lastCmdRunTimeOnServer;
void Clear();
// returns true if the entity shouldn't be spawned at all in this game type or difficulty level
bool InhibitEntitySpawn( idDict &spawnArgs );
// spawn entities from the map file
void SpawnMapEntities();
// commons used by init, shutdown, and restart
void MapPopulate();
void MapClear( bool clearClients );
pvsHandle_t GetClientPVS( idPlayer *player, pvsType_t type );
void SetupPlayerPVS();
void FreePlayerPVS();
void UpdateGravity();
void SortActiveEntityList();
void ShowTargets();
void RunDebugInfo();
void InitScriptForMap();
void SetScriptFPS( const float com_engineHz );
void SpawnPlayer( int clientNum );
void InitConsoleCommands();
void ShutdownConsoleCommands();
void InitAsyncNetwork();
void ShutdownAsyncNetwork();
void NetworkEventWarning( const entityNetEvent_t *event, VERIFY_FORMAT_STRING const char *fmt, ... );
void ServerProcessEntityNetworkEventQueue();
void ClientProcessEntityNetworkEventQueue();
// call after any change to serverInfo. Will update various quick-access flags
void UpdateServerInfoFlags();
void RandomizeInitialSpawns();
static int sortSpawnPoints( const void *ptr1, const void *ptr2 );
bool SimulateProjectiles();
};
//============================================================================
extern idGameLocal gameLocal;
extern idAnimManager animationLib;
//============================================================================
class idGameError : public idException {
public:
idGameError( const char *text ) : idException( text ) {}
};
//============================================================================
template< class type >
ID_INLINE idEntityPtr<type>::idEntityPtr() {
spawnId = 0;
}
template< class type >
ID_INLINE void idEntityPtr<type>::Save( idSaveGame *savefile ) const {
savefile->WriteInt( spawnId );
}
template< class type >
ID_INLINE void idEntityPtr<type>::Restore( idRestoreGame *savefile ) {
savefile->ReadInt( spawnId );
}
template< class type >
ID_INLINE idEntityPtr<type> &idEntityPtr<type>::operator=( const type *ent ) {
if ( ent == NULL ) {
spawnId = 0;
} else {
spawnId = ( gameLocal.spawnIds[ent->entityNumber] << GENTITYNUM_BITS ) | ent->entityNumber;
}
return *this;
}
template< class type >
ID_INLINE idEntityPtr< type > &idEntityPtr<type>::operator=( const idEntityPtr & ep ) {
spawnId = ep.spawnId;
return *this;
}
template< class type >
ID_INLINE bool idEntityPtr<type>::SetSpawnId( int id ) {
// the reason for this first check is unclear:
// the function returning false may mean the spawnId is already set right, or the entity is missing
if ( id == spawnId ) {
return false;
}
if ( ( id >> GENTITYNUM_BITS ) == gameLocal.spawnIds[ id & ( ( 1 << GENTITYNUM_BITS ) - 1 ) ] ) {
spawnId = id;
return true;
}
return false;
}
template< class type >
ID_INLINE bool idEntityPtr<type>::IsValid() const {
return ( gameLocal.spawnIds[ spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ) ] == ( spawnId >> GENTITYNUM_BITS ) );
}
template< class type >
ID_INLINE type *idEntityPtr<type>::GetEntity() const {
int entityNum = spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 );
if ( ( gameLocal.spawnIds[ entityNum ] == ( spawnId >> GENTITYNUM_BITS ) ) ) {
return static_cast<type *>( gameLocal.entities[ entityNum ] );
}
return NULL;
}
template< class type >
ID_INLINE int idEntityPtr<type>::GetEntityNum() const {
return ( spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ) );
}
// ===========================================================================
//
// these defines work for all startsounds from all entity types
// make sure to change script/doom_defs.script if you add any channels, or change their order
//
typedef enum {
SND_CHANNEL_ANY = SCHANNEL_ANY,
SND_CHANNEL_VOICE = SCHANNEL_ONE,
SND_CHANNEL_VOICE2,
SND_CHANNEL_BODY,
SND_CHANNEL_BODY2,
SND_CHANNEL_BODY3,
SND_CHANNEL_WEAPON,
SND_CHANNEL_ITEM,
SND_CHANNEL_HEART,
SND_CHANNEL_PDA_AUDIO,
SND_CHANNEL_PDA_VIDEO,
SND_CHANNEL_DEMONIC,
SND_CHANNEL_RADIO,
// internal use only. not exposed to script or framecommands.
SND_CHANNEL_AMBIENT,
SND_CHANNEL_DAMAGE
} gameSoundChannel_t;
// content masks
#define MASK_ALL (-1)
#define MASK_SOLID (CONTENTS_SOLID)
#define MASK_MONSTERSOLID (CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_BODY)
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_BODY)
#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP)
#define MASK_WATER (CONTENTS_WATER)
#define MASK_OPAQUE (CONTENTS_OPAQUE)
#define MASK_SHOT_RENDERMODEL (CONTENTS_SOLID|CONTENTS_RENDERMODEL)
#define MASK_SHOT_BOUNDINGBOX (CONTENTS_SOLID|CONTENTS_BODY)
const float DEFAULT_GRAVITY = 1066.0f;
#define DEFAULT_GRAVITY_STRING "1066"
const idVec3 DEFAULT_GRAVITY_VEC3( 0, 0, -DEFAULT_GRAVITY );
const int CINEMATIC_SKIP_DELAY = SEC2MS( 2.0f );
//============================================================================
#include "physics/Force.h"
#include "physics/Force_Constant.h"
#include "physics/Force_Drag.h"
#include "physics/Force_Grab.h"
#include "physics/Force_Field.h"
#include "physics/Force_Spring.h"
#include "physics/Physics.h"
#include "physics/Physics_Static.h"
#include "physics/Physics_StaticMulti.h"
#include "physics/Physics_Base.h"
#include "physics/Physics_Actor.h"
#include "physics/Physics_Monster.h"
#include "physics/Physics_Player.h"
#include "physics/Physics_Parametric.h"
#include "physics/Physics_RigidBody.h"
#include "physics/Physics_AF.h"
#include "SmokeParticles.h"
#include "Entity.h"
#include "GameEdit.h"
#include "Grabber.h"
#include "AF.h"
#include "IK.h"
#include "AFEntity.h"
#include "Misc.h"
#include "Actor.h"
#include "Projectile.h"
#include "Weapon.h"
#include "Light.h"
#include "WorldSpawn.h"
#include "Item.h"
#include "PlayerView.h"
#include "PlayerIcon.h"
#include "Achievements.h"
#include "AimAssist.h"
#include "Player.h"
#include "Mover.h"
#include "Camera.h"
#include "Moveable.h"
#include "Target.h"
#include "Trigger.h"
#include "Sound.h"
#include "Fx.h"
#include "SecurityCamera.h"
#include "BrittleFracture.h"
#include "ai/AI.h"
#include "anim/Anim_Testmodel.h"
// menus
#include "menus/MenuWidget.h"
#include "menus/MenuScreen.h"
#include "menus/MenuHandler.h"
#include "script/Script_Compiler.h"
#include "script/Script_Interpreter.h"
#include "script/Script_Thread.h"
#endif /* !__GAME_LOCAL_H__ */

1328
neo/d3xp/Game_network.cpp Normal file

File diff suppressed because it is too large Load Diff

739
neo/d3xp/Grabber.cpp Normal file
View File

@@ -0,0 +1,739 @@
/*
===========================================================================
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.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
#include "Misc.h"
#define MAX_DRAG_TRACE_DISTANCE 384.0f
#define TRACE_BOUNDS_SIZE 3.f
#define HOLD_DISTANCE 72.f
#define FIRING_DELAY 1000.0f
#define DRAG_FAIL_LEN 64.f
#define THROW_SCALE 1000
#define MAX_PICKUP_VELOCITY 1500 * 1500
#define MAX_PICKUP_SIZE 96
/*
===============================================================================
Allows entities to be dragged through the world with physics.
===============================================================================
*/
CLASS_DECLARATION( idEntity, idGrabber )
END_CLASS
/*
==============
idGrabber::idGrabber
==============
*/
idGrabber::idGrabber() {
dragEnt = NULL;
owner = NULL;
beam = NULL;
beamTarget = NULL;
oldImpulseSequence = 0;
shakeForceFlip = false;
holdingAF = false;
endTime = 0;
lastFiredTime = -FIRING_DELAY;
dragFailTime = 0;
startDragTime = 0;
warpId = -1;
dragTraceDist = MAX_DRAG_TRACE_DISTANCE;
}
/*
==============
idGrabber::~idGrabber
==============
*/
idGrabber::~idGrabber() {
StopDrag( true );
if ( beam ) {
delete beam;
}
if ( beamTarget ) {
delete beamTarget;
}
}
/*
==============
idGrabber::Save
==============
*/
void idGrabber::Save( idSaveGame *savefile ) const {
dragEnt.Save( savefile );
savefile->WriteStaticObject( drag );
savefile->WriteVec3( saveGravity );
savefile->WriteInt( id );
savefile->WriteVec3( localPlayerPoint );
owner.Save( savefile );
savefile->WriteBool( holdingAF );
savefile->WriteBool( shakeForceFlip );
savefile->WriteInt( endTime );
savefile->WriteInt( lastFiredTime );
savefile->WriteInt( dragFailTime );
savefile->WriteInt( startDragTime );
savefile->WriteFloat( dragTraceDist );
savefile->WriteInt( savedContents );
savefile->WriteInt( savedClipmask );
savefile->WriteObject( beam );
savefile->WriteObject( beamTarget );
savefile->WriteInt( warpId );
}
/*
==============
idGrabber::Restore
==============
*/
void idGrabber::Restore( idRestoreGame *savefile ) {
//Spawn the beams
Initialize();
dragEnt.Restore( savefile );
savefile->ReadStaticObject( drag );
savefile->ReadVec3( saveGravity );
savefile->ReadInt( id );
// Restore the drag force's physics object
if ( dragEnt.IsValid() ) {
drag.SetPhysics( dragEnt.GetEntity()->GetPhysics(), id, dragEnt.GetEntity()->GetPhysics()->GetOrigin() );
}
savefile->ReadVec3( localPlayerPoint );
owner.Restore( savefile );
savefile->ReadBool( holdingAF );
savefile->ReadBool( shakeForceFlip );
savefile->ReadInt( endTime );
savefile->ReadInt( lastFiredTime );
savefile->ReadInt( dragFailTime );
savefile->ReadInt( startDragTime );
savefile->ReadFloat( dragTraceDist );
savefile->ReadInt( savedContents );
savefile->ReadInt( savedClipmask );
savefile->ReadObject( reinterpret_cast<idClass *&>(beam) );
savefile->ReadObject( reinterpret_cast<idClass *&>(beamTarget) );
savefile->ReadInt( warpId );
}
/*
==============
idGrabber::Initialize
==============
*/
void idGrabber::Initialize() {
if ( !common->IsMultiplayer() ) {
idDict args;
if ( !beamTarget ) {
args.SetVector( "origin", vec3_origin );
args.SetBool( "start_off", true );
beamTarget = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
}
if ( !beam ) {
args.Clear();
args.Set( "target", beamTarget->name.c_str() );
args.SetVector( "origin", vec3_origin );
args.SetBool( "start_off", true );
args.Set( "width", "6" );
args.Set( "skin", "textures/smf/flareSizeable" );
args.Set( "_color", "0.0235 0.843 0.969 0.2" );
beam = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
beam->SetShaderParm( 6, 1.0f );
}
endTime = 0;
dragTraceDist = MAX_DRAG_TRACE_DISTANCE;
}
else {
beam = NULL;
beamTarget = NULL;
endTime = 0;
dragTraceDist = MAX_DRAG_TRACE_DISTANCE;
};
}
/*
==============
idGrabber::SetDragDistance
==============
*/
void idGrabber::SetDragDistance( float dist ) {
dragTraceDist = dist;
}
/*
==============
idGrabber::StartDrag
==============
*/
void idGrabber::StartDrag( idEntity *grabEnt, int id ) {
int clipModelId = id;
idPlayer *thePlayer = owner.GetEntity();
holdingAF = false;
dragFailTime = gameLocal.slow.time;
startDragTime = gameLocal.slow.time;
oldImpulseSequence = thePlayer->usercmd.impulseSequence;
// set grabbed state for networking
grabEnt->SetGrabbedState( true );
// This is the new object to drag around
dragEnt = grabEnt;
// Show the beams!
UpdateBeams();
if ( beam ) {
beam->Show();
}
if ( beamTarget ) {
beamTarget->Show();
}
// Move the object to the fast group (helltime)
grabEnt->timeGroup = TIME_GROUP2;
// Handle specific class types
if ( grabEnt->IsType( idProjectile::Type ) ) {
idProjectile* p = (idProjectile*)grabEnt;
p->CatchProjectile( thePlayer, "_catch" );
// Make the projectile non-solid to other projectiles/enemies (special hack for helltime hunter)
if ( !idStr::Cmp( grabEnt->GetEntityDefName(), "projectile_helltime_killer" ) ) {
savedContents = CONTENTS_PROJECTILE;
savedClipmask = MASK_SHOT_RENDERMODEL|CONTENTS_PROJECTILE;
} else {
savedContents = grabEnt->GetPhysics()->GetContents();
savedClipmask = grabEnt->GetPhysics()->GetClipMask();
}
grabEnt->GetPhysics()->SetContents( 0 );
grabEnt->GetPhysics()->SetClipMask( CONTENTS_SOLID|CONTENTS_BODY );
} else if ( grabEnt->IsType( idExplodingBarrel::Type ) ) {
idExplodingBarrel *ebarrel = static_cast<idExplodingBarrel*>(grabEnt);
ebarrel->StartBurning();
} else if ( grabEnt->IsType( idAFEntity_Gibbable::Type ) ) {
holdingAF = true;
clipModelId = 0;
if ( grabbableAI( grabEnt->spawnArgs.GetString( "classname" ) ) ) {
idAI *aiEnt = static_cast<idAI*>(grabEnt);
aiEnt->StartRagdoll();
}
} else if ( grabEnt->IsType( idMoveableItem::Type ) ) {
grabEnt->PostEventMS( &EV_Touch, 250, thePlayer, NULL );
}
// Get the current physics object to manipulate
idPhysics *phys = grabEnt->GetPhysics();
// Turn off gravity on object
saveGravity = phys->GetGravity();
phys->SetGravity( vec3_origin );
// hold it directly in front of player
localPlayerPoint = ( thePlayer->firstPersonViewAxis[0] * HOLD_DISTANCE ) * thePlayer->firstPersonViewAxis.Transpose();
// Set the ending time for the hold
endTime = gameLocal.time + g_grabberHoldSeconds.GetFloat() * 1000;
// Start up the Force_Drag to bring it in
drag.Init( g_grabberDamping.GetFloat() );
drag.SetPhysics( phys, clipModelId, thePlayer->firstPersonViewOrigin + localPlayerPoint * thePlayer->firstPersonViewAxis);
// start the screen warp
warpId = thePlayer->playerView.AddWarp( phys->GetOrigin(), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 160, 2000 );
}
/*
==============
idGrabber::StopDrag
==============
*/
void idGrabber::StopDrag( bool dropOnly ) {
idPlayer *thePlayer = owner.GetEntity();
if ( beam ) {
beam->Hide();
}
if ( beamTarget ) {
beamTarget->Hide();
}
if ( dragEnt.IsValid() ) {
idEntity *ent = dragEnt.GetEntity();
// set grabbed state for networking
ent->SetGrabbedState( false );
// If a cinematic has started, allow dropped object to think in cinematics
if ( gameLocal.inCinematic ) {
ent->cinematic = true;
}
// Restore Gravity
ent->GetPhysics()->SetGravity( saveGravity );
// Move the object back to the slow group (helltime)
ent->timeGroup = TIME_GROUP1;
if ( holdingAF ) {
idAFEntity_Gibbable *af = static_cast<idAFEntity_Gibbable *>(ent);
idPhysics_AF *af_Phys = static_cast<idPhysics_AF*>(af->GetPhysics());
if ( grabbableAI( ent->spawnArgs.GetString( "classname" ) ) ) {
idAI *aiEnt = static_cast<idAI*>(ent);
aiEnt->Damage( thePlayer, thePlayer, vec3_origin, "damage_suicide", 1.0f, INVALID_JOINT );
}
af->SetThrown( !dropOnly );
// Reset timers so that it isn't forcibly put to rest in mid-air
af_Phys->PutToRest();
af_Phys->Activate();
af_Phys->SetTimeScaleRamp( MS2SEC(gameLocal.slow.time) - 1.5f, MS2SEC(gameLocal.slow.time) + 1.0f );
}
// If the object isn't near its goal, just drop it in place.
if ( !ent->IsType( idProjectile::Type ) && ( dropOnly || drag.GetDistanceToGoal() > DRAG_FAIL_LEN ) ) {
ent->GetPhysics()->SetLinearVelocity( vec3_origin );
thePlayer->StartSoundShader( declManager->FindSound( "grabber_maindrop" ), SND_CHANNEL_WEAPON, 0, false, NULL );
if ( ent->IsType( idExplodingBarrel::Type ) ) {
idExplodingBarrel *ebarrel = static_cast<idExplodingBarrel*>(ent);
ebarrel->SetStability( true );
ebarrel->StopBurning();
}
} else {
// Shoot the object forward
ent->ApplyImpulse( thePlayer, 0, ent->GetPhysics()->GetOrigin(), thePlayer->firstPersonViewAxis[0] * THROW_SCALE * ent->GetPhysics()->GetMass() );
thePlayer->StartSoundShader( declManager->FindSound( "grabber_release" ), SND_CHANNEL_WEAPON, 0, false, NULL );
// Orient projectiles away from the player
if ( ent->IsType( idProjectile::Type ) ) {
idPlayer *player = owner.GetEntity();
idAngles ang = player->firstPersonViewAxis[0].ToAngles();
ang.pitch += 90.f;
ent->GetPhysics()->SetAxis( ang.ToMat3() );
ent->GetPhysics()->SetAngularVelocity( vec3_origin );
// Restore projectile contents
ent->GetPhysics()->SetContents( savedContents );
ent->GetPhysics()->SetClipMask( savedClipmask );
idProjectile *projectile = static_cast< idProjectile* >( ent );
if ( projectile != NULL ) {
projectile->SetLaunchedFromGrabber( true );
}
} else if ( ent->IsType( idMoveable::Type ) ) {
// Turn on damage for this object
idMoveable *obj = static_cast<idMoveable*>(ent);
obj->EnableDamage( true, 2.5f );
obj->SetAttacker( thePlayer );
if ( ent->IsType( idExplodingBarrel::Type ) ) {
idExplodingBarrel *ebarrel = static_cast<idExplodingBarrel*>(ent);
ebarrel->SetStability( false );
}
} else if ( ent->IsType( idMoveableItem::Type ) ) {
ent->GetPhysics()->SetClipMask( MASK_MONSTERSOLID );
}
}
// Remove the Force_Drag's control of the entity
drag.RemovePhysics( ent->GetPhysics() );
}
if ( warpId != -1 ) {
thePlayer->playerView.FreeWarp( warpId );
warpId = -1;
}
lastFiredTime = gameLocal.time;
dragEnt = NULL;
endTime = 0;
}
/*
==============
idGrabber::Update
==============
*/
int idGrabber::Update( idPlayer *player, bool hide ) {
trace_t trace;
idEntity *newEnt;
// pause before allowing refire
if ( lastFiredTime + FIRING_DELAY > gameLocal.time ) {
return 3;
}
// Dead players release the trigger
if ( hide || player->health <= 0 ) {
StopDrag( true );
if ( hide ) {
lastFiredTime = gameLocal.time - FIRING_DELAY + 250;
}
return 3;
}
// Check if object being held has been removed (dead demon, projectile, etc.)
if ( endTime > gameLocal.time ) {
bool abort = !dragEnt.IsValid();
if ( !abort && dragEnt.GetEntity()->IsType( idProjectile::Type ) ) {
idProjectile *proj = (idProjectile *)dragEnt.GetEntity();
if ( proj->GetProjectileState() >= 3 ) {
abort = true;
}
}
if ( !abort && dragEnt.GetEntity() && dragEnt.GetEntity()->IsHidden() ) {
abort = true;
}
// Not in multiplayer :: Pressing "reload" lets you carefully drop an item
if ( !common->IsMultiplayer() && !abort && ( player->usercmd.impulseSequence != oldImpulseSequence ) && (player->usercmd.impulse == IMPULSE_13) ) {
abort = true;
}
if ( abort ) {
StopDrag( true );
return 3;
}
}
owner = player;
// if no entity selected for dragging
if ( !dragEnt.GetEntity() ) {
idBounds bounds;
idVec3 end = player->firstPersonViewOrigin + player->firstPersonViewAxis[0] * dragTraceDist;
bounds.Zero();
bounds.ExpandSelf( TRACE_BOUNDS_SIZE );
gameLocal.clip.TraceBounds( trace, player->firstPersonViewOrigin, end, bounds, MASK_SHOT_RENDERMODEL|CONTENTS_PROJECTILE|CONTENTS_MOVEABLECLIP, player );
// If the trace hit something
if ( trace.fraction < 1.0f ) {
newEnt = gameLocal.entities[ trace.c.entityNum ];
// if entity is already being grabbed then bypass
if ( common->IsMultiplayer() && newEnt && newEnt->IsGrabbed() ) {
return 0;
}
// Check if this is a valid entity to hold
if ( newEnt && ( newEnt->IsType( idMoveable::Type ) ||
newEnt->IsType( idMoveableItem::Type ) ||
newEnt->IsType( idProjectile::Type ) ||
newEnt->IsType( idAFEntity_Gibbable::Type )
) &&
newEnt->noGrab == false &&
newEnt->GetPhysics()->GetBounds().GetRadius() < MAX_PICKUP_SIZE &&
newEnt->GetPhysics()->GetLinearVelocity().LengthSqr() < MAX_PICKUP_VELOCITY ) {
bool validAF = true;
if ( newEnt->IsType( idAFEntity_Gibbable::Type ) ) {
idAFEntity_Gibbable *afEnt = static_cast<idAFEntity_Gibbable*>(newEnt);
if ( grabbableAI( newEnt->spawnArgs.GetString( "classname" ) ) ) {
// Make sure it's also active
if ( !afEnt->IsActive() ) {
validAF = false;
}
} else if ( !afEnt->IsActiveAF() ) {
validAF = false;
}
}
if ( validAF && player->usercmd.buttons & BUTTON_ATTACK ) {
// Grab this entity and start dragging it around
StartDrag( newEnt, trace.c.id );
} else if ( validAF ) {
// A holdable object is ready to be grabbed
return 1;
}
}
}
}
// check backwards server time in multiplayer
bool allow = true;
if ( common->IsMultiplayer() ) {
// if we've marched backwards
if ( gameLocal.slow.time < startDragTime ) {
allow = false;
}
}
// if there is an entity selected for dragging
if ( dragEnt.GetEntity() && allow ) {
idPhysics *entPhys = dragEnt.GetEntity()->GetPhysics();
idVec3 goalPos;
// If the player lets go of attack, or time is up
if ( !( player->usercmd.buttons & BUTTON_ATTACK ) ) {
StopDrag( false );
return 3;
}
if ( gameLocal.time > endTime ) {
StopDrag( true );
return 3;
}
// Check if the player is standing on the object
if ( !holdingAF ) {
idBounds playerBounds;
idBounds objectBounds = entPhys->GetAbsBounds();
idVec3 newPoint = player->GetPhysics()->GetOrigin();
// create a bounds at the players feet
playerBounds.Clear();
playerBounds.AddPoint( newPoint );
newPoint.z -= 1.f;
playerBounds.AddPoint( newPoint );
playerBounds.ExpandSelf( 8.f );
// If it intersects the object bounds, then drop it
if ( playerBounds.IntersectsBounds( objectBounds ) ) {
StopDrag( true );
return 3;
}
}
// Shake the object at the end of the hold
if ( g_grabberEnableShake.GetBool() && !common->IsMultiplayer() ) {
ApplyShake();
}
// Set and evaluate drag force
goalPos = player->firstPersonViewOrigin + localPlayerPoint * player->firstPersonViewAxis;
drag.SetGoalPosition( goalPos );
drag.Evaluate( gameLocal.time );
// If an object is flying too fast toward the player, stop it hard
if ( g_grabberHardStop.GetBool() ) {
idPlane theWall;
idVec3 toPlayerVelocity, objectCenter;
float toPlayerSpeed;
toPlayerVelocity = -player->firstPersonViewAxis[0];
toPlayerSpeed = entPhys->GetLinearVelocity() * toPlayerVelocity;
if ( toPlayerSpeed > 64.f ) {
objectCenter = entPhys->GetAbsBounds().GetCenter();
theWall.SetNormal( player->firstPersonViewAxis[0] );
theWall.FitThroughPoint( goalPos );
if ( theWall.Side( objectCenter, 0.1f ) == PLANESIDE_BACK ) {
int i, num;
num = entPhys->GetNumClipModels();
for ( i=0; i<num; i++ ) {
entPhys->SetLinearVelocity( vec3_origin, i );
}
}
}
// Make sure the object isn't spinning too fast
const float MAX_ROTATION_SPEED = 12.f;
idVec3 angVel = entPhys->GetAngularVelocity();
float rotationSpeed = angVel.LengthFast();
if ( rotationSpeed > MAX_ROTATION_SPEED ) {
angVel.NormalizeFast();
angVel *= MAX_ROTATION_SPEED;
entPhys->SetAngularVelocity( angVel );
}
}
// Orient projectiles away from the player
if ( dragEnt.GetEntity()->IsType( idProjectile::Type ) ) {
idAngles ang = player->firstPersonViewAxis[0].ToAngles();
ang.pitch += 90.f;
entPhys->SetAxis( ang.ToMat3() );
}
// Some kind of effect from gun to object?
UpdateBeams();
// If the object is stuck away from its intended position for more than 500ms, let it go.
if ( drag.GetDistanceToGoal() > DRAG_FAIL_LEN ) {
if ( dragFailTime < (gameLocal.slow.time - 500) ) {
StopDrag( true );
return 3;
}
} else {
dragFailTime = gameLocal.slow.time;
}
// Currently holding an object
return 2;
}
// Not holding, nothing to hold
return 0;
}
/*
======================
idGrabber::UpdateBeams
======================
*/
void idGrabber::UpdateBeams() {
jointHandle_t muzzle_joint;
idVec3 muzzle_origin;
idMat3 muzzle_axis;
renderEntity_t *re;
if ( !beam ) {
return;
}
if ( dragEnt.IsValid() ) {
idPlayer *thePlayer = owner.GetEntity();
if ( beamTarget ) {
beamTarget->SetOrigin( dragEnt.GetEntity()->GetPhysics()->GetAbsBounds().GetCenter() );
}
muzzle_joint = thePlayer->weapon.GetEntity()->GetAnimator()->GetJointHandle( "particle_upper" );
if ( muzzle_joint != INVALID_JOINT ) {
thePlayer->weapon.GetEntity()->GetJointWorldTransform( muzzle_joint, gameLocal.time, muzzle_origin, muzzle_axis );
} else {
muzzle_origin = thePlayer->GetPhysics()->GetOrigin();
}
beam->SetOrigin( muzzle_origin );
re = beam->GetRenderEntity();
re->origin = muzzle_origin;
beam->UpdateVisuals();
beam->Present();
}
}
/*
==============
idGrabber::ApplyShake
==============
*/
void idGrabber::ApplyShake() {
float u = 1 - (float)( endTime - gameLocal.time ) / ( g_grabberHoldSeconds.GetFloat() * 1000 );
if ( u >= 0.8f ) {
idVec3 point, impulse;
float shakeForceMagnitude = 450.f;
float mass = dragEnt.GetEntity()->GetPhysics()->GetMass();
shakeForceFlip = !shakeForceFlip;
// get point to rotate around
point = dragEnt.GetEntity()->GetPhysics()->GetOrigin();
point.y += 1;
// Articulated figures get less violent shake
if ( holdingAF ) {
shakeForceMagnitude = 120.f;
}
// calc impulse
if ( shakeForceFlip ) {
impulse.Set( 0, 0, shakeForceMagnitude * u * mass );
}
else {
impulse.Set( 0, 0, -shakeForceMagnitude * u * mass );
}
dragEnt.GetEntity()->ApplyImpulse( NULL, 0, point, impulse );
}
}
/*
==============
idGrabber::grabbableAI
==============
*/
bool idGrabber::grabbableAI( const char *aiName ) {
// skip "monster_"
aiName += 8;
if (!idStr::Cmpn( aiName, "flying_lostsoul", 15 ) ||
!idStr::Cmpn( aiName, "demon_trite", 11 ) ||
!idStr::Cmp( aiName, "flying_forgotten" ) ||
!idStr::Cmp( aiName, "demon_cherub" ) ||
!idStr::Cmp( aiName, "demon_tick" )) {
return true;
}
return false;
}

84
neo/d3xp/Grabber.h Normal file
View File

@@ -0,0 +1,84 @@
/*
===========================================================================
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.
===========================================================================
*/
/*
===============================================================================
Grabber Object - Class to extend idWeapon to include functionality for
manipulating physics objects.
===============================================================================
*/
class idBeam;
class idGrabber : public idEntity {
public:
CLASS_PROTOTYPE( idGrabber );
idGrabber();
~idGrabber();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Initialize();
void SetDragDistance( float dist );
int Update( idPlayer *player, bool hide );
private:
idEntityPtr<idEntity> dragEnt; // entity being dragged
idForce_Grab drag;
idVec3 saveGravity;
int id; // id of body being dragged
idVec3 localPlayerPoint; // dragged point in player space
idEntityPtr<idPlayer> owner;
int oldImpulseSequence;
bool holdingAF;
bool shakeForceFlip;
int endTime;
int lastFiredTime;
int dragFailTime;
int startDragTime;
float dragTraceDist;
int savedContents;
int savedClipmask;
idBeam* beam;
idBeam* beamTarget;
int warpId;
bool grabbableAI( const char *aiName );
void StartDrag( idEntity *grabEnt, int id );
void StopDrag( bool dropOnly );
void UpdateBeams();
void ApplyShake();
};

1128
neo/d3xp/IK.cpp Normal file

File diff suppressed because it is too large Load Diff

182
neo/d3xp/IK.h Normal file
View File

@@ -0,0 +1,182 @@
/*
===========================================================================
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 __GAME_IK_H__
#define __GAME_IK_H__
/*
===============================================================================
IK base class with a simple fast two bone solver.
===============================================================================
*/
#define IK_ANIM "ik_pose"
class idIK {
public:
idIK();
virtual ~idIK();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
bool IsInitialized() const;
virtual bool Init( idEntity *self, const char *anim, const idVec3 &modelOffset );
virtual void Evaluate();
virtual void ClearJointMods();
bool SolveTwoBones( const idVec3 &startPos, const idVec3 &endPos, const idVec3 &dir, float len0, float len1, idVec3 &jointPos );
float GetBoneAxis( const idVec3 &startPos, const idVec3 &endPos, const idVec3 &dir, idMat3 &axis );
protected:
bool initialized;
bool ik_activate;
idEntity * self; // entity using the animated model
idAnimator * animator; // animator on entity
int modifiedAnim; // animation modified by the IK
idVec3 modelOffset;
};
/*
===============================================================================
IK controller for a walking character with an arbitrary number of legs.
===============================================================================
*/
class idIK_Walk : public idIK {
public:
idIK_Walk();
virtual ~idIK_Walk();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual bool Init( idEntity *self, const char *anim, const idVec3 &modelOffset );
virtual void Evaluate();
virtual void ClearJointMods();
void EnableAll();
void DisableAll();
void EnableLeg( int num );
void DisableLeg( int num );
private:
static const int MAX_LEGS = 8;
idClipModel * footModel;
int numLegs;
int enabledLegs;
jointHandle_t footJoints[MAX_LEGS];
jointHandle_t ankleJoints[MAX_LEGS];
jointHandle_t kneeJoints[MAX_LEGS];
jointHandle_t hipJoints[MAX_LEGS];
jointHandle_t dirJoints[MAX_LEGS];
jointHandle_t waistJoint;
idVec3 hipForward[MAX_LEGS];
idVec3 kneeForward[MAX_LEGS];
float upperLegLength[MAX_LEGS];
float lowerLegLength[MAX_LEGS];
idMat3 upperLegToHipJoint[MAX_LEGS];
idMat3 lowerLegToKneeJoint[MAX_LEGS];
float smoothing;
float waistSmoothing;
float footShift;
float waistShift;
float minWaistFloorDist;
float minWaistAnkleDist;
float footUpTrace;
float footDownTrace;
bool tiltWaist;
bool usePivot;
// state
int pivotFoot;
float pivotYaw;
idVec3 pivotPos;
bool oldHeightsValid;
float oldWaistHeight;
float oldAnkleHeights[MAX_LEGS];
idVec3 waistOffset;
};
/*
===============================================================================
IK controller for reaching a position with an arm or leg.
===============================================================================
*/
class idIK_Reach : public idIK {
public:
idIK_Reach();
virtual ~idIK_Reach();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual bool Init( idEntity *self, const char *anim, const idVec3 &modelOffset );
virtual void Evaluate();
virtual void ClearJointMods();
private:
static const int MAX_ARMS = 2;
int numArms;
int enabledArms;
jointHandle_t handJoints[MAX_ARMS];
jointHandle_t elbowJoints[MAX_ARMS];
jointHandle_t shoulderJoints[MAX_ARMS];
jointHandle_t dirJoints[MAX_ARMS];
idVec3 shoulderForward[MAX_ARMS];
idVec3 elbowForward[MAX_ARMS];
float upperArmLength[MAX_ARMS];
float lowerArmLength[MAX_ARMS];
idMat3 upperArmToShoulderJoint[MAX_ARMS];
idMat3 lowerArmToElbowJoint[MAX_ARMS];
};
#endif /* !__GAME_IK_H__ */

2138
neo/d3xp/Item.cpp Normal file

File diff suppressed because it is too large Load Diff

324
neo/d3xp/Item.h Normal file
View File

@@ -0,0 +1,324 @@
/*
===========================================================================
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 __GAME_ITEM_H__
#define __GAME_ITEM_H__
/*
===============================================================================
Items the player can pick up or use.
===============================================================================
*/
/*
================================================
These flags are passed to the Give functions
to set their behavior. We need to be able to
separate the feedback from the actual
state modification so that we can hide lag
on MP clients.
For the previous behavior of functions which
take a giveFlags parameter (this is usually
desired on the server too) pass
ITEM_GIVE_FEEDBACK | ITEM_GIVE_UPDATE_STATE.
================================================
*/
enum itemGiveFlags_t {
ITEM_GIVE_FEEDBACK = BIT( 0 ),
ITEM_GIVE_UPDATE_STATE = BIT( 1 ),
ITEM_GIVE_FROM_WEAPON = BIT( 2 ), // indicates this was given via a weapon's launchPowerup (for bloodstone powerups)
};
class idItem : public idEntity {
public:
CLASS_PROTOTYPE( idItem );
idItem();
virtual ~idItem();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
void GetAttributes( idDict &attributes ) const;
virtual bool GiveToPlayer( idPlayer *player, unsigned int giveFlags );
virtual bool Pickup( idPlayer *player );
virtual void Think();
virtual void Present();
enum {
EVENT_PICKUP = idEntity::EVENT_MAXEVENTS,
EVENT_RESPAWN,
EVENT_RESPAWNFX,
EVENT_TAKEFLAG,
EVENT_DROPFLAG,
EVENT_FLAGRETURN,
EVENT_FLAGCAPTURE,
EVENT_MAXEVENTS
};
void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void ClientPredictionThink();
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
// networking
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
protected:
int GetPredictPickupMilliseconds() const { return clientPredictPickupMilliseconds; }
private:
idVec3 orgOrigin;
bool spin;
bool pulse;
bool canPickUp;
// for item pulse effect
int itemShellHandle;
const idMaterial * shellMaterial;
// used to update the item pulse effect
mutable bool inView;
mutable int inViewTime;
mutable int lastCycle;
mutable int lastRenderViewTime;
// used for prediction in mp
int clientPredictPickupMilliseconds;
bool UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView ) const;
static bool ModelCallback( renderEntity_s *renderEntity, const renderView_t *renderView );
void Event_DropToFloor();
void Event_Touch( idEntity *other, trace_t *trace );
void Event_Trigger( idEntity *activator );
void Event_Respawn();
void Event_RespawnFx();
};
class idItemPowerup : public idItem {
public:
CLASS_PROTOTYPE( idItemPowerup );
idItemPowerup();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
virtual bool GiveToPlayer( idPlayer *player, unsigned int giveFlags );
private:
int time;
int type;
};
class idObjective : public idItem {
public:
CLASS_PROTOTYPE( idObjective );
idObjective();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
private:
idVec3 playerPos;
const idMaterial * screenshot;
void Event_Trigger( idEntity *activator );
void Event_HideObjective( idEntity *e );
void Event_GetPlayerPos();
};
class idVideoCDItem : public idItem {
public:
CLASS_PROTOTYPE( idVideoCDItem );
virtual bool GiveToPlayer( idPlayer *player, unsigned int giveFlags );
};
class idPDAItem : public idItem {
public:
CLASS_PROTOTYPE( idPDAItem );
virtual bool GiveToPlayer( idPlayer *player, unsigned int giveFlags );
};
class idMoveableItem : public idItem {
public:
CLASS_PROTOTYPE( idMoveableItem );
idMoveableItem();
virtual ~idMoveableItem();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
virtual void Think();
void ClientThink( const int curTime, const float fraction, const bool predict );
virtual bool Collide( const trace_t &collision, const idVec3 &velocity );
virtual bool Pickup( idPlayer *player );
static void DropItems( idAnimatedEntity *ent, const char *type, idList<idEntity *> *list );
static idEntity * DropItem( const char *classname, const idVec3 &origin, const idMat3 &axis, const idVec3 &velocity, int activateDelay, int removeDelay );
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
protected:
idPhysics_RigidBody physicsObj;
idClipModel * trigger;
const idDeclParticle * smoke;
int smokeTime;
int nextSoundTime;
bool repeatSmoke; // never stop updating the particles
void Gib( const idVec3 &dir, const char *damageDefName );
void Event_DropToFloor();
void Event_Gib( const char *damageDefName );
};
class idItemTeam : public idMoveableItem {
public:
CLASS_PROTOTYPE( idItemTeam );
idItemTeam();
virtual ~idItemTeam();
void Spawn();
virtual bool Pickup( idPlayer *player );
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
virtual void Think(void );
void Drop( bool death = false ); // was the drop caused by death of carrier?
void Return( idPlayer * player = NULL );
void Capture();
virtual void FreeLightDef();
virtual void Present();
// networking
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
public:
int team;
// TODO : turn this into a state :
bool carried; // is it beeing carried by a player?
bool dropped; // was it dropped?
private:
idVec3 returnOrigin;
idMat3 returnAxis;
int lastDrop;
const idDeclSkin * skinDefault;
const idDeclSkin * skinCarried;
const function_t * scriptTaken;
const function_t * scriptDropped;
const function_t * scriptReturned;
const function_t * scriptCaptured;
renderLight_t itemGlow; // Used by flags when they are picked up
int itemGlowHandle;
int lastNuggetDrop;
const char * nuggetName;
private:
void Event_TakeFlag( idPlayer * player );
void Event_DropFlag( bool death );
void Event_FlagReturn( idPlayer * player = NULL );
void Event_FlagCapture();
void PrivateReturn();
function_t * LoadScript( char * script );
void SpawnNugget( idVec3 pos );
void UpdateGuis();
};
class idMoveablePDAItem : public idMoveableItem {
public:
CLASS_PROTOTYPE( idMoveablePDAItem );
virtual bool GiveToPlayer( idPlayer *player, unsigned int giveFlags );
};
/*
===============================================================================
Item removers.
===============================================================================
*/
class idItemRemover : public idEntity {
public:
CLASS_PROTOTYPE( idItemRemover );
void Spawn();
void RemoveItem( idPlayer *player );
private:
void Event_Trigger( idEntity *activator );
};
class idObjectiveComplete : public idItemRemover {
public:
CLASS_PROTOTYPE( idObjectiveComplete );
idObjectiveComplete();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
private:
idVec3 playerPos;
void Event_Trigger( idEntity *activator );
void Event_HideObjective( idEntity *e );
void Event_GetPlayerPos();
};
#endif /* !__GAME_ITEM_H__ */

332
neo/d3xp/Leaderboards.cpp Normal file
View File

@@ -0,0 +1,332 @@
/*
===========================================================================
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.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
#include "Leaderboards.h"
#include "MultiplayerGame.h"
/*
================================================================================================
Leaderboard stats column definitions - per Game Type.
================================================================================================
*/
static columnDef_t public_Deathmatch[] = {
{ "Frags", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
//{ "Deaths", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
//{ "Wins", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
//{ "Score", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
};
static columnDef_t public_Tourney[] = {
{ "Wins", 64, AGGREGATE_SUM, STATS_COLUMN_DISPLAY_NUMBER },
};
static columnDef_t public_TeamDeathmatch[] = {
{ "Wins", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
};
static columnDef_t public_LastmanStanding[] = {
{ "Wins", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
};
static columnDef_t public_CaptureTheFlag[] = {
{ "Wins", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
};
// This should match up to the ordering of the gameType_t. ( in MultiplayerGame.h )
const columnGameMode_t gameMode_columnDefs[] = {
{ public_Deathmatch, ARRAY_COUNT( public_Deathmatch ), RANK_GREATEST_FIRST, false, false, "DM" }, // DEATHMATCH
{ public_Tourney, ARRAY_COUNT( public_Tourney ), RANK_GREATEST_FIRST, false, false, "TOURNEY" }, // TOURNEY
{ public_TeamDeathmatch, ARRAY_COUNT( public_TeamDeathmatch ), RANK_GREATEST_FIRST, false, false, "TDM" }, // TEAM DEATHMATCH
{ public_LastmanStanding, ARRAY_COUNT( public_LastmanStanding ), RANK_GREATEST_FIRST, false, false, "LMS" }, // LASTMAN STANDING
{ public_CaptureTheFlag, ARRAY_COUNT( public_CaptureTheFlag ), RANK_GREATEST_FIRST, false, false, "CTF" }, // CAPTURE THE FLAG
};
/*
=====================================
RetreiveLeaderboardID
Each map will move in blocks of n*modes.
ex. map 0 will have 0 - 4 Leaderboard id's blocked out.
map 1 will have 5 - 10 leaderboard id's blocked out.
if gamemode is added it will move in blocks of ARRAY_COUNT( modes )
=====================================
*/
int LeaderboardLocal_GetID( int mapIndex, int gametype ) {
assert( gametype > GAME_RANDOM );
return mapIndex * ARRAY_COUNT( gameMode_columnDefs ) + gametype;
}
/*
=====================================
LeaderboardLocal_Init
=====================================
*/
void LeaderboardLocal_Init() {
const idList< mpMap_t > maps = common->GetMapList();
const char ** gameModes = NULL;
const char ** gameModesDisplay = NULL;
int numModes = game->GetMPGameModes( &gameModes, &gameModesDisplay );
// Iterate through all the available maps, and generate leaderboard Defs, and IDs for each.
for( int mapIdx = 0; mapIdx < maps.Num(); mapIdx++ ) {
for( int modeIdx = 0; modeIdx < numModes; modeIdx++ ) {
// Check the supported modes on the map.
if( maps[ mapIdx ].supportedModes & BIT( modeIdx ) ) {
const columnGameMode_t gamemode = gameMode_columnDefs[ modeIdx ];
// Generate a Leaderboard ID for the map/mode
int boardID = LeaderboardLocal_GetID( mapIdx, modeIdx );
// Create and Register the leaderboard with the sys_stats registered Leaderboards
leaderboardDefinition_t * newLeaderboardDef = Sys_CreateLeaderboardDef( boardID,
gamemode.numColumns,
gamemode.columnDef,
gamemode.rankOrder,
gamemode.supportsAttachments,
gamemode.checkAgainstCurrent );
// Set the leaderboard name.
const char* mapname = idLocalization::GetString( maps[ mapIdx ].mapName );
newLeaderboardDef->boardName.Format( "%s %s", mapname, gamemode.abrevName );
// sanity check.
if( Sys_FindLeaderboardDef( boardID ) != newLeaderboardDef ) {
idLib::Error( "Leaderboards_Init leaderboard creation failed" );
}
}
}
}
}
/*
=====================================
LeaderboardLocal_Shutdown
=====================================
*/
void LeaderboardLocal_Shutdown() {
Sys_DestroyLeaderboardDefs();
}
/*
=====================================
LeaderboardLocal_Upload
=====================================
*/
const static int FRAG_MULTIPLIER = 100;
const static int DEATH_MULTIPLIER = -50;
const static int WINS_MULTIPLIER = 20;
void LeaderboardLocal_Upload( lobbyUserID_t lobbyUserID,int gameType, leaderboardStats_t & stats ) {
assert( gameType > GAME_RANDOM );
int mapIdx = 0;
// Need to figure out What stat columns we want to base rank on. ( for now we'll use wins )
const column_t * gameTypeColumn = NULL;
const column_t defaultStats[] = { stats.wins };
// calculate DM score.
int dmScore = stats.frags * FRAG_MULTIPLIER + stats.deaths * DEATH_MULTIPLIER + stats.wins * WINS_MULTIPLIER ;
// TODO: Once leaderboard menu has correct columns- enable this -> const column_t dmStats[] = { stats.frags, stats.deaths, stats.wins, dmScore };
const column_t dmStats[] = { dmScore };
// Calculate TDM score.
int tdmScore = stats.frags * FRAG_MULTIPLIER + stats.teamfrags * FRAG_MULTIPLIER + stats.deaths * DEATH_MULTIPLIER + stats.wins * WINS_MULTIPLIER ;
const column_t tdmStats[] = { tdmScore };
// Calculate Tourney score.
int tourneyScore = stats.wins;
const column_t tnyStats[] = { tourneyScore };
// Calculate LMS score.
int lmsFrags = stats.frags;
if( lmsFrags < 0 ) {
lmsFrags = 0; // LMS NO LIVES LEFT = -20 on fragCount.
}
int lmsScore = lmsFrags * FRAG_MULTIPLIER + stats.wins * ( WINS_MULTIPLIER * 10 ) ;
const column_t lmsStats[] = { lmsScore };
// Calculate CTF score.
int ctfScore = stats.frags * FRAG_MULTIPLIER + stats.deaths * DEATH_MULTIPLIER + stats.wins * ( WINS_MULTIPLIER * 10 );
const column_t ctfStats[] = { ctfScore };
switch( gameType ) {
case GAME_DM:
gameTypeColumn = dmStats;
break;
case GAME_TDM:
gameTypeColumn = tdmStats;
break;
case GAME_TOURNEY:
gameTypeColumn = tnyStats;
break;
case GAME_LASTMAN:
gameTypeColumn = lmsStats;
break;
case GAME_CTF: {
gameTypeColumn = ctfStats;
break;
}
default:
gameTypeColumn = defaultStats;
}
const idMatchParameters & matchParameters = session->GetActingGameStateLobbyBase().GetMatchParms();
const idList< mpMap_t > maps = common->GetMapList();
// need to find the map Index number
for( mapIdx = 0; mapIdx < maps.Num(); mapIdx++ ) {
if( matchParameters.mapName.Cmp( maps[ mapIdx ].mapFile ) == 0 ) {
break;
}
}
int boardID = LeaderboardLocal_GetID( mapIdx, gameType );
const leaderboardDefinition_t * board = Sys_FindLeaderboardDef( boardID );
if( board ) {
session->LeaderboardUpload( lobbyUserID, board, gameTypeColumn );
} else {
idLib::Warning( "LeaderboardLocal_Upload invalid leaderboard with id of %d", boardID );
}
}
class idLeaderboardCallbackTest : public idLeaderboardCallback {
void Call() {
idLib::Printf( "Leaderboard information retrieved in user callback.\n" );
idLib::Printf( "%d total entries in leaderboard %d.\n", numRowsInLeaderboard, def->id );
for ( int i = 0; i < rows.Num(); i++ ) {
idLib::Printf( "%d: %s rank:%lld", i, rows[i].name.c_str(), rows[i].rank );
for ( int j = 0; j < def->numColumns; j++ ) {
idLib::Printf( ", score[%d]: %lld", j, rows[i].columns[j] );
}
idLib::Printf( "\n" );
}
}
idLeaderboardCallback * Clone() const {
return new (TAG_PSN) idLeaderboardCallbackTest( *this );
}
};
CONSOLE_COMMAND( testLeaderboardDownload, "<id 0 - n > <start = 1> <end = 100>", 0 ) {
idLeaderboardCallbackTest leaderboardCallbackTest;
int leaderboardID = 0;
int start = 1;
int end = 100;
if ( args.Argc() > 1 ) {
leaderboardID = atoi( args.Argv( 1 ) );
}
if ( args.Argc() > 2 ) {
start = atoi( args.Argv( 2 ) );
}
if ( args.Argc() > 3 ) {
end = atoi( args.Argv( 3 ) );
}
const leaderboardDefinition_t * leaderboardDef = Sys_FindLeaderboardDef( leaderboardID );
if( leaderboardDef ) {
session->LeaderboardDownload( 0, leaderboardDef, start, end, leaderboardCallbackTest );
} else {
idLib::Warning( "Sys_FindLeaderboardDef() Unable to find board %d\n", leaderboardID );
}
}
CONSOLE_COMMAND( testLeaderboardUpload, "<gameType 0 - 4 > <frags = 0> <wins = 1>", 0 ) {
idLobbyBase & lobby = session->GetActingGameStateLobbyBase();
lobbyUserID_t user = lobby.GetLobbyUserIdByOrdinal( 0 );
gameType_t gameType = GAME_DM;
int frags = 0;
int wins = 1;
if ( args.Argc() > 1 ) {
gameType = static_cast<gameType_t>( atoi( args.Argv( 1 ) ) );
}
if ( args.Argc() > 2 ) {
frags = atoi( args.Argv( 2 ) );
}
if ( args.Argc() > 3 ) {
wins = atoi( args.Argv( 3 ) );
}
leaderboardStats_t stats = { frags, wins, 0, 0 };
LeaderboardLocal_Upload( user, gameType , stats );
session->LeaderboardFlush();
}
CONSOLE_COMMAND( testLeaderboardUpload_SendToClients, "<gameType 0 - 4 > <frags = 0> <wins = 1>", 0 ) {
for( int playerIdx = 0; playerIdx < gameLocal.numClients; playerIdx++ ) {
leaderboardStats_t stats = { 1, 1, 1, 1 };
LeaderboardLocal_Upload( gameLocal.lobbyUserIDs[ playerIdx ], gameLocal.gameType, stats );
}
// Dont do this more than once.
session->LeaderboardFlush();
}

74
neo/d3xp/Leaderboards.h Normal file
View File

@@ -0,0 +1,74 @@
/*
===========================================================================
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 __LEADERBOARDS_LOCAL_H__
#define __LEADERBOARDS_LOCAL_H__
struct leaderboardStats_t {
int frags;
int wins;
int teamfrags;
int deaths;
};
struct columnGameMode_t {
columnDef_t * columnDef; // The Column definition for the game mode.
int numColumns;
rankOrder_t rankOrder; // rank ordering of the game mode. ( RANK_GREATEST_FIRST, RANK_LEAST_FIRST )
bool supportsAttachments;
bool checkAgainstCurrent;
const char * abrevName; // Leaderboard Game Mode Abrev.
};
/*
================================================================================================
Leaderboards
================================================================================================
*/
// creates and stores all the leaderboards inside the internal map ( see Sys_FindLeaderboardDef on retrieving definition )
void LeaderboardLocal_Init();
// Destroys any leaderboard definitions allocated by LeaderboardLocal_Init()
void LeaderboardLocal_Shutdown();
// Gets a leaderboard ID with map index and game type.
int LeaderboardLocal_GetID( int mapIndex, int gametype );
// Do it all function. Will create the column_t with the correct stats from the game type, and upload it to the leaderboard system.
void LeaderboardLocal_Upload( lobbyUserID_t lobbyUserID, int gameType, leaderboardStats_t & stats );
extern const columnGameMode_t gameMode_columnDefs[];
#endif // __LEADERBOARDS_LOCAL_H__

1182
neo/d3xp/Light.cpp Normal file

File diff suppressed because it is too large Load Diff

142
neo/d3xp/Light.h Normal file
View File

@@ -0,0 +1,142 @@
/*
===========================================================================
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 __GAME_LIGHT_H__
#define __GAME_LIGHT_H__
/*
===============================================================================
Generic light.
===============================================================================
*/
extern const idEventDef EV_Light_GetLightParm;
extern const idEventDef EV_Light_SetLightParm;
extern const idEventDef EV_Light_SetLightParms;
class idLight : public idEntity {
public:
CLASS_PROTOTYPE( idLight );
idLight();
~idLight();
void Spawn();
void Save( idSaveGame *savefile ) const; // archives object for save game file
void Restore( idRestoreGame *savefile ); // unarchives object from save game file
virtual void UpdateChangeableSpawnArgs( const idDict *source );
virtual void Think();
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void FreeLightDef();
virtual bool GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis );
void Present();
void SaveState( idDict *args );
virtual void SetColor( float red, float green, float blue );
virtual void SetColor( const idVec4 &color );
void SetColor( const idVec3 &color );
virtual void GetColor( idVec3 &out ) const;
virtual void GetColor( idVec4 &out ) const;
const idVec3 & GetBaseColor() const { return baseColor; }
void SetShader( const char *shadername );
void SetLightParm( int parmnum, float value );
void SetLightParms( float parm0, float parm1, float parm2, float parm3 );
void SetRadiusXYZ( float x, float y, float z );
void SetRadius( float radius );
void On();
void Off();
void Fade( const idVec4 &to, float fadeTime );
void FadeOut( float time );
void FadeIn( float time );
void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
void BecomeBroken( idEntity *activator );
qhandle_t GetLightDefHandle() const { return lightDefHandle; }
void SetLightParent( idEntity *lparent ) { lightParent = lparent; }
void SetLightLevel();
virtual void ShowEditingDialog();
enum {
EVENT_BECOMEBROKEN = idEntity::EVENT_MAXEVENTS,
EVENT_MAXEVENTS
};
virtual void ClientPredictionThink();
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
private:
renderLight_t renderLight; // light presented to the renderer
idVec3 localLightOrigin; // light origin relative to the physics origin
idMat3 localLightAxis; // light axis relative to physics axis
qhandle_t lightDefHandle; // handle to renderer light def
idStr brokenModel;
int levels;
int currentLevel;
idVec3 baseColor;
// Colors used for client-side interpolation.
idVec3 previousBaseColor;
idVec3 nextBaseColor;
bool breakOnTrigger;
int count;
int triggercount;
idEntity * lightParent;
idVec4 fadeFrom;
idVec4 fadeTo;
int fadeStart;
int fadeEnd;
bool soundWasPlaying;
private:
void PresentLightDefChange();
void PresentModelDefChange();
void Event_SetShader( const char *shadername );
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_SetRadiusXYZ( float x, float y, float z );
void Event_SetRadius( float radius );
void Event_Hide();
void Event_Show();
void Event_On();
void Event_Off();
void Event_ToggleOnOff( idEntity *activator );
void Event_SetSoundHandles();
void Event_FadeOut( float time );
void Event_FadeIn( float time );
};
#endif /* !__GAME_LIGHT_H__ */

3934
neo/d3xp/Misc.cpp Normal file

File diff suppressed because it is too large Load Diff

928
neo/d3xp/Misc.h Normal file
View File

@@ -0,0 +1,928 @@
/*
===========================================================================
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 __GAME_MISC_H__
#define __GAME_MISC_H__
/*
===============================================================================
idSpawnableEntity
A simple, spawnable entity with a model and no functionable ability of it's own.
For example, it can be used as a placeholder during development, for marking
locations on maps for script, or for simple placed models without any behavior
that can be bound to other entities. Should not be subclassed.
===============================================================================
*/
class idSpawnableEntity : public idEntity {
public:
CLASS_PROTOTYPE( idSpawnableEntity );
void Spawn();
private:
};
/*
===============================================================================
Potential spawning position for players.
The first time a player enters the game, they will be at an 'initial' spot.
Targets will be fired when someone spawns in on them.
When triggered, will cause player to be teleported to spawn spot.
===============================================================================
*/
class idPlayerStart : public idEntity {
public:
CLASS_PROTOTYPE( idPlayerStart );
enum {
EVENT_TELEPORTPLAYER = idEntity::EVENT_MAXEVENTS,
EVENT_MAXEVENTS
};
idPlayerStart();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
private:
int teleportStage;
void Event_TeleportPlayer( idEntity *activator );
void Event_TeleportStage( idEntity *player );
void TeleportPlayer( idPlayer *player );
};
/*
===============================================================================
Non-displayed entity used to activate triggers when it touches them.
Bind to a mover to have the mover activate a trigger as it moves.
When target by triggers, activating the trigger will toggle the
activator on and off. Check "start_off" to have it spawn disabled.
===============================================================================
*/
class idActivator : public idEntity {
public:
CLASS_PROTOTYPE( idActivator );
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
private:
bool stay_on;
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
Path entities for monsters to follow.
===============================================================================
*/
class idPathCorner : public idEntity {
public:
CLASS_PROTOTYPE( idPathCorner );
void Spawn();
static void DrawDebugInfo();
static idPathCorner *RandomPath( const idEntity *source, const idEntity *ignore );
private:
void Event_RandomPath();
};
/*
===============================================================================
Object that fires targets and changes shader parms when damaged.
===============================================================================
*/
class idDamagable : public idEntity {
public:
CLASS_PROTOTYPE( idDamagable );
idDamagable();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
virtual void Hide();
virtual void Show();
private:
int count;
int nextTriggerTime;
void BecomeBroken( idEntity *activator );
void Event_BecomeBroken( idEntity *activator );
void Event_RestoreDamagable();
};
/*
===============================================================================
Hidden object that explodes when activated
===============================================================================
*/
class idExplodable : public idEntity {
public:
CLASS_PROTOTYPE( idExplodable );
void Spawn();
private:
void Event_Explode( idEntity *activator );
};
/*
===============================================================================
idSpring
===============================================================================
*/
class idSpring : public idEntity {
public:
CLASS_PROTOTYPE( idSpring );
void Spawn();
virtual void Think();
private:
idEntity * ent1;
idEntity * ent2;
int id1;
int id2;
idVec3 p1;
idVec3 p2;
idForce_Spring spring;
void Event_LinkSpring();
};
/*
===============================================================================
idForceField
===============================================================================
*/
class idForceField : public idEntity {
public:
CLASS_PROTOTYPE( idForceField );
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
virtual void Think();
virtual void ClientThink( const int curTime, const float fraction, const bool predict ) ;
private:
idForce_Field forceField;
void Toggle();
void Event_Activate( idEntity *activator );
void Event_Toggle();
void Event_FindTargets();
};
/*
===============================================================================
idAnimated
===============================================================================
*/
class idAnimated : public idAFEntity_Gibbable {
public:
CLASS_PROTOTYPE( idAnimated );
idAnimated();
~idAnimated();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
virtual bool LoadAF();
bool StartRagdoll();
virtual bool GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis );
private:
int num_anims;
int current_anim_index;
int anim;
int blendFrames;
jointHandle_t soundJoint;
idEntityPtr<idEntity> activator;
bool activated;
int achievement;
void PlayNextAnim();
void Event_Activate( idEntity *activator );
void Event_Start();
void Event_StartRagdoll();
void Event_AnimDone( int animIndex );
void Event_Footstep();
void Event_LaunchMissiles( const char *projectilename, const char *sound, const char *launchjoint, const char *targetjoint, int numshots, int framedelay );
void Event_LaunchMissilesUpdate( int launchjoint, int targetjoint, int numshots, int framedelay );
void Event_SetAnimation( const char *animName );
void Event_GetAnimationLength();
};
/*
===============================================================================
idStaticEntity
===============================================================================
*/
class idStaticEntity : public idEntity {
public:
CLASS_PROTOTYPE( idStaticEntity );
idStaticEntity();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
void ShowEditingDialog();
virtual void Hide();
virtual void Show();
void Fade( const idVec4 &to, float fadeTime );
virtual void Think();
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
private:
void Event_Activate( idEntity *activator );
int spawnTime;
bool active;
idVec4 fadeFrom;
idVec4 fadeTo;
int fadeStart;
int fadeEnd;
bool runGui;
};
/*
===============================================================================
idFuncEmitter
===============================================================================
*/
class idFuncEmitter : public idStaticEntity {
public:
CLASS_PROTOTYPE( idFuncEmitter );
idFuncEmitter();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
void Event_Activate( idEntity *activator );
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
private:
bool hidden;
};
/*
===============================================================================
idFuncShootProjectile
===============================================================================
*/
class idFuncShootProjectile : public idStaticEntity {
public:
CLASS_PROTOTYPE( idFuncShootProjectile );
idFuncShootProjectile();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
void Event_Activate( idEntity *activator );
virtual void Think();
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
private:
int mRespawnDelay;
int mRespawnTime;
float mShootSpeed;
idVec3 mShootDir;
idStr mEntityDefName;
idEntityPtr< idEntity > mLastProjectile;
};
/*
===============================================================================
idFuncSmoke
===============================================================================
*/
class idFuncSmoke : public idEntity {
public:
CLASS_PROTOTYPE( idFuncSmoke );
idFuncSmoke();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
void Event_Activate( idEntity *activator );
private:
int smokeTime;
const idDeclParticle * smoke;
bool restart;
};
/*
===============================================================================
idFuncSplat
===============================================================================
*/
class idFuncSplat : public idFuncEmitter {
public:
CLASS_PROTOTYPE( idFuncSplat );
idFuncSplat();
void Spawn();
private:
void Event_Activate( idEntity *activator );
void Event_Splat();
};
/*
===============================================================================
idTextEntity
===============================================================================
*/
class idTextEntity : public idEntity {
public:
CLASS_PROTOTYPE( idTextEntity );
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
private:
idStr text;
bool playerOriented;
};
/*
===============================================================================
idLocationEntity
===============================================================================
*/
class idLocationEntity : public idEntity {
public:
CLASS_PROTOTYPE( idLocationEntity );
void Spawn();
const char * GetLocation() const;
private:
};
class idLocationSeparatorEntity : public idEntity {
public:
CLASS_PROTOTYPE( idLocationSeparatorEntity );
void Spawn();
private:
};
class idVacuumSeparatorEntity : public idEntity {
public:
CLASS_PROTOTYPE( idVacuumSeparatorEntity );
idVacuumSeparatorEntity();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Event_Activate( idEntity *activator );
private:
qhandle_t portal;
};
class idVacuumEntity : public idEntity {
public:
CLASS_PROTOTYPE( idVacuumEntity );
void Spawn();
private:
};
/*
===============================================================================
idBeam
===============================================================================
*/
class idBeam : public idEntity {
public:
CLASS_PROTOTYPE( idBeam );
idBeam();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
void SetMaster( idBeam *masterbeam );
void SetBeamTarget( const idVec3 &origin );
virtual void Show();
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
private:
void Event_MatchTarget();
void Event_Activate( idEntity *activator );
idEntityPtr<idBeam> target;
idEntityPtr<idBeam> master;
};
/*
===============================================================================
idLiquid
===============================================================================
*/
class idRenderModelLiquid;
class idLiquid : public idEntity {
public:
CLASS_PROTOTYPE( idLiquid );
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
private:
void Event_Touch( idEntity *other, trace_t *trace );
idRenderModelLiquid *model;
};
/*
===============================================================================
idShaking
===============================================================================
*/
class idShaking : public idEntity {
public:
CLASS_PROTOTYPE( idShaking );
idShaking();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
private:
idPhysics_Parametric physicsObj;
bool active;
void BeginShaking();
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idEarthQuake
===============================================================================
*/
class idEarthQuake : public idEntity {
public:
CLASS_PROTOTYPE( idEarthQuake );
idEarthQuake();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
private:
int nextTriggerTime;
int shakeStopTime;
float wait;
float random;
bool triggered;
bool playerOriented;
bool disabled;
float shakeTime;
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idFuncPortal
===============================================================================
*/
class idFuncPortal : public idEntity {
public:
CLASS_PROTOTYPE( idFuncPortal );
idFuncPortal();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
private:
qhandle_t portal;
bool state;
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idFuncAASPortal
===============================================================================
*/
class idFuncAASPortal : public idEntity {
public:
CLASS_PROTOTYPE( idFuncAASPortal );
idFuncAASPortal();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
private:
bool state;
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idFuncAASObstacle
===============================================================================
*/
class idFuncAASObstacle : public idEntity {
public:
CLASS_PROTOTYPE( idFuncAASObstacle );
idFuncAASObstacle();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
private:
bool state;
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idFuncRadioChatter
===============================================================================
*/
class idFuncRadioChatter : public idEntity {
public:
CLASS_PROTOTYPE( idFuncRadioChatter );
idFuncRadioChatter();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
private:
float time;
void Event_Activate( idEntity *activator );
void Event_ResetRadioHud( idEntity *activator );
};
/*
===============================================================================
idPhantomObjects
===============================================================================
*/
class idPhantomObjects : public idEntity {
public:
CLASS_PROTOTYPE( idPhantomObjects );
idPhantomObjects();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
private:
void Event_Activate( idEntity *activator );
void Event_Throw();
void Event_ShakeObject( idEntity *object, int starttime );
int end_time;
float throw_time;
float shake_time;
idVec3 shake_ang;
float speed;
int min_wait;
int max_wait;
idEntityPtr<idActor>target;
idList<int> targetTime;
idList<idVec3> lastTargetPos;
};
/*
===============================================================================
idShockwave
===============================================================================
*/
class idShockwave : public idEntity {
public:
CLASS_PROTOTYPE( idShockwave );
idShockwave();
~idShockwave();
void Spawn();
void Think();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
private:
void Event_Activate( idEntity *activator );
bool isActive;
int startTime;
int duration;
float startSize;
float endSize;
float currentSize;
float magnitude;
float height;
bool playerDamaged;
float playerDamageSize;
};
/*
===============================================================================
idFuncMountedObject
===============================================================================
*/
class idFuncMountedObject : public idEntity {
public:
CLASS_PROTOTYPE( idFuncMountedObject );
idFuncMountedObject();
~idFuncMountedObject();
void Spawn();
void Think();
void GetAngleRestrictions( int &yaw_min, int &yaw_max, int &pitch );
private:
int harc;
int varc;
void Event_Touch( idEntity *other, trace_t *trace );
void Event_Activate( idEntity *activator );
public:
bool isMounted;
function_t * scriptFunction;
idPlayer * mountedPlayer;
};
class idFuncMountedWeapon : public idFuncMountedObject {
public:
CLASS_PROTOTYPE( idFuncMountedWeapon );
idFuncMountedWeapon();
~idFuncMountedWeapon();
void Spawn();
void Think();
private:
// The actual turret that moves with the player's view
idEntity * turret;
// the muzzle bone's position, used for launching projectiles and trailing smoke
idVec3 muzzleOrigin;
idMat3 muzzleAxis;
float weaponLastFireTime;
float weaponFireDelay;
const idDict * projectile;
const idSoundShader *soundFireWeapon;
void Event_PostSpawn();
};
/*
===============================================================================
idPortalSky
===============================================================================
*/
class idPortalSky : public idEntity {
public:
CLASS_PROTOTYPE( idPortalSky );
idPortalSky();
~idPortalSky();
void Spawn();
void Event_PostSpawn();
void Event_Activate( idEntity *activator );
};
#endif /* !__GAME_MISC_H__ */

1355
neo/d3xp/Moveable.cpp Normal file

File diff suppressed because it is too large Load Diff

210
neo/d3xp/Moveable.h Normal file
View File

@@ -0,0 +1,210 @@
/*
===========================================================================
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 __GAME_MOVEABLE_H__
#define __GAME_MOVEABLE_H__
/*
===============================================================================
Entity using rigid body physics.
===============================================================================
*/
extern const idEventDef EV_BecomeNonSolid;
extern const idEventDef EV_IsAtRest;
class idMoveable : public idEntity {
public:
CLASS_PROTOTYPE( idMoveable );
idMoveable();
~idMoveable();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void Hide();
virtual void Show();
bool AllowStep() const;
void EnableDamage( bool enable, float duration );
virtual bool Collide( const trace_t &collision, const idVec3 &velocity );
virtual void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
void SetAttacker( idEntity *ent );
const idEntity * GetAttacker() { return attacker; }
protected:
idPhysics_RigidBody physicsObj; // physics object
idStr brokenModel; // model set when health drops down to or below zero
idStr damage; // if > 0 apply damage to hit entities
idStr monsterDamage;
idEntity *attacker;
idStr fxCollide; // fx system to start when collides with something
int nextCollideFxTime; // next time it is ok to spawn collision fx
float minDamageVelocity; // minimum velocity before moveable applies damage
float maxDamageVelocity; // velocity at which the maximum damage is applied
idCurve_Spline<idVec3> *initialSpline; // initial spline path the moveable follows
idVec3 initialSplineDir; // initial relative direction along the spline path
bool explode; // entity explodes when health drops down to or below zero
bool unbindOnDeath; // unbind from master when health drops down to or below zero
bool allowStep; // allow monsters to step on the object
bool canDamage; // only apply damage when this is set
int nextDamageTime; // next time the movable can hurt the player
int nextSoundTime; // next time the moveable can make a sound
const idMaterial * GetRenderModelMaterial() const;
void BecomeNonSolid();
void InitInitialSpline( int startTime );
bool FollowInitialSplinePath();
void Event_Activate( idEntity *activator );
void Event_BecomeNonSolid();
void Event_SetOwnerFromSpawnArgs();
void Event_IsAtRest();
void Event_EnableDamage( float enable );
};
/*
===============================================================================
A barrel using rigid body physics. The barrel has special handling of
the view model orientation to make it look like it rolls instead of slides.
===============================================================================
*/
class idBarrel : public idMoveable {
public:
CLASS_PROTOTYPE( idBarrel );
idBarrel();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void BarrelThink();
virtual void Think();
virtual bool GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis );
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
private:
float radius; // radius of barrel
int barrelAxis; // one of the coordinate axes the barrel cylinder is parallel to
idVec3 lastOrigin; // origin of the barrel the last think frame
idMat3 lastAxis; // axis of the barrel the last think frame
float additionalRotation; // additional rotation of the barrel about it's axis
idMat3 additionalAxis; // additional rotation axis
};
/*
===============================================================================
A barrel using rigid body physics and special handling of the view model
orientation to make it look like it rolls instead of slides. The barrel
can burn and explode when damaged.
===============================================================================
*/
class idExplodingBarrel : public idBarrel {
public:
CLASS_PROTOTYPE( idExplodingBarrel );
idExplodingBarrel();
~idExplodingBarrel();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
bool IsStable();
void SetStability( bool stability );
void StartBurning();
void StopBurning();
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void Think();
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir,
const char *damageDefName, const float damageScale, const int location );
virtual void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
enum {
EVENT_EXPLODE = idEntity::EVENT_MAXEVENTS,
EVENT_MAXEVENTS
};
private:
typedef enum {
NORMAL = 0,
BURNING,
BURNEXPIRED,
EXPLODING
} explode_state_t;
explode_state_t state;
idVec3 spawnOrigin;
idMat3 spawnAxis;
qhandle_t particleModelDefHandle;
qhandle_t lightDefHandle;
renderEntity_t particleRenderEntity;
renderLight_t light;
int particleTime;
int lightTime;
float time;
bool isStable;
void AddParticles( const char *name, bool burn );
void AddLight( const char *name , bool burn );
void ExplodingEffects();
void UpdateLight();
void Event_Activate( idEntity *activator );
void Event_Respawn();
void Event_Explode();
void Event_TriggerTargets();
};
#endif /* !__GAME_MOVEABLE_H__ */

4852
neo/d3xp/Mover.cpp Normal file

File diff suppressed because it is too large Load Diff

556
neo/d3xp/Mover.h Normal file
View File

@@ -0,0 +1,556 @@
/*
===========================================================================
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 __GAME_MOVER_H__
#define __GAME_MOVER_H__
extern const idEventDef EV_TeamBlocked;
extern const idEventDef EV_PartBlocked;
extern const idEventDef EV_ReachedPos;
extern const idEventDef EV_ReachedAng;
/*
===============================================================================
General movers.
===============================================================================
*/
class idMover : public idEntity {
public:
CLASS_PROTOTYPE( idMover );
idMover();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
virtual void Hide();
virtual void Show();
void SetPortalState( bool open );
protected:
typedef enum {
ACCELERATION_STAGE,
LINEAR_STAGE,
DECELERATION_STAGE,
FINISHED_STAGE
} moveStage_t;
typedef enum {
MOVER_NONE,
MOVER_ROTATING,
MOVER_MOVING,
MOVER_SPLINE
} moverCommand_t;
//
// mover directions. make sure to change script/doom_defs.script if you add any, or change their order
//
typedef enum {
DIR_UP = -1,
DIR_DOWN = -2,
DIR_LEFT = -3,
DIR_RIGHT = -4,
DIR_FORWARD = -5,
DIR_BACK = -6,
DIR_REL_UP = -7,
DIR_REL_DOWN = -8,
DIR_REL_LEFT = -9,
DIR_REL_RIGHT = -10,
DIR_REL_FORWARD = -11,
DIR_REL_BACK = -12
} moverDir_t;
typedef struct {
moveStage_t stage;
int acceleration;
int movetime;
int deceleration;
idVec3 dir;
} moveState_t;
typedef struct {
moveStage_t stage;
int acceleration;
int movetime;
int deceleration;
idAngles rot;
} rotationState_t;
idPhysics_Parametric physicsObj;
void Event_OpenPortal();
void Event_ClosePortal();
void Event_PartBlocked( idEntity *blockingEntity );
void MoveToPos( const idVec3 &pos);
void UpdateMoveSound( moveStage_t stage );
void UpdateRotationSound( moveStage_t stage );
void SetGuiStates( const char *state );
void FindGuiTargets();
void SetGuiState( const char *key, const char *val ) const;
virtual void DoneMoving();
virtual void DoneRotating();
virtual void BeginMove( idThread *thread = NULL );
virtual void BeginRotation( idThread *thread, bool stopwhendone );
moveState_t move;
private:
rotationState_t rot;
int move_thread;
int rotate_thread;
idAngles dest_angles;
idAngles angle_delta;
idVec3 dest_position;
idVec3 move_delta;
float move_speed;
int move_time;
int deceltime;
int acceltime;
bool stopRotation;
bool useSplineAngles;
idEntityPtr<idEntity> splineEnt;
moverCommand_t lastCommand;
float damage;
qhandle_t areaPortal; // 0 = no portal
idList< idEntityPtr<idEntity>, TAG_MOVER > guiTargets;
void VectorForDir( float dir, idVec3 &vec );
idCurve_Spline<idVec3> *GetSpline( idEntity *splineEntity ) const;
void Event_SetCallback();
void Event_TeamBlocked( idEntity *blockedPart, idEntity *blockingEntity );
void Event_StopMoving();
void Event_StopRotating();
void Event_UpdateMove();
void Event_UpdateRotation();
void Event_SetMoveSpeed( float speed );
void Event_SetMoveTime( float time );
void Event_SetDecelerationTime( float time );
void Event_SetAccellerationTime( float time );
void Event_MoveTo( idEntity *ent );
void Event_MoveToPos( idVec3 &pos );
void Event_MoveDir( float angle, float distance );
void Event_MoveAccelerateTo( float speed, float time );
void Event_MoveDecelerateTo( float speed, float time );
void Event_RotateDownTo( int axis, float angle );
void Event_RotateUpTo( int axis, float angle );
void Event_RotateTo( idAngles &angles );
void Event_Rotate( idAngles &angles );
void Event_RotateOnce( idAngles &angles );
void Event_Bob( float speed, float phase, idVec3 &depth );
void Event_Sway( float speed, float phase, idAngles &depth );
void Event_SetAccelSound( const char *sound );
void Event_SetDecelSound( const char *sound );
void Event_SetMoveSound( const char *sound );
void Event_FindGuiTargets();
void Event_InitGuiTargets();
void Event_EnableSplineAngles();
void Event_DisableSplineAngles();
void Event_RemoveInitialSplineAngles();
void Event_StartSpline( idEntity *splineEntity );
void Event_StopSpline();
void Event_Activate( idEntity *activator );
void Event_PostRestore( int start, int total, int accel, int decel, int useSplineAng );
void Event_IsMoving();
void Event_IsRotating();
};
class idSplinePath : public idEntity {
public:
CLASS_PROTOTYPE( idSplinePath );
idSplinePath();
void Spawn();
};
struct floorInfo_s {
idVec3 pos;
idStr door;
int floor;
};
class idElevator : public idMover {
public:
CLASS_PROTOTYPE( idElevator );
idElevator();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual bool HandleSingleGuiCommand( idEntity *entityGui, idLexer *src );
void Event_GotoFloor( int floor );
floorInfo_s * GetFloorInfo( int floor );
protected:
virtual void DoneMoving();
virtual void BeginMove( idThread *thread = NULL );
void SpawnTrigger( const idVec3 &pos );
void GetLocalTriggerPosition();
void Event_Touch( idEntity *other, trace_t *trace );
private:
typedef enum {
INIT,
IDLE,
WAITING_ON_DOORS
} elevatorState_t;
elevatorState_t state;
idList<floorInfo_s, TAG_MOVER> floorInfo;
int currentFloor;
int pendingFloor;
int lastFloor;
bool controlsDisabled;
float returnTime;
int returnFloor;
int lastTouchTime;
class idDoor * GetDoor( const char *name );
void Think();
void OpenInnerDoor();
void OpenFloorDoor( int floor );
void CloseAllDoors();
void DisableAllDoors();
void EnableProperDoors();
void Event_TeamBlocked( idEntity *blockedEntity, idEntity *blockingEntity );
void Event_Activate( idEntity *activator );
void Event_PostFloorArrival();
void Event_SetGuiStates();
};
/*
===============================================================================
Binary movers.
===============================================================================
*/
typedef enum {
MOVER_POS1,
MOVER_POS2,
MOVER_1TO2,
MOVER_2TO1
} moverState_t;
class idMover_Binary : public idEntity {
public:
CLASS_PROTOTYPE( idMover_Binary );
idMover_Binary();
~idMover_Binary();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void PreBind();
virtual void PostBind();
void Enable( bool b );
void InitSpeed( idVec3 &mpos1, idVec3 &mpos2, float mspeed, float maccelTime, float mdecelTime );
void InitTime( idVec3 &mpos1, idVec3 &mpos2, float mtime, float maccelTime, float mdecelTime );
void GotoPosition1();
void GotoPosition2();
void Use_BinaryMover( idEntity *activator );
void SetGuiStates( const char *state );
void UpdateBuddies( int val );
idMover_Binary * GetActivateChain() const { return activateChain; }
idMover_Binary * GetMoveMaster() const { return moveMaster; }
void BindTeam( idEntity *bindTo );
void SetBlocked( bool b );
bool IsBlocked();
idEntity * GetActivator() const;
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
void SetPortalState( bool open );
protected:
idVec3 pos1;
idVec3 pos2;
moverState_t moverState;
idMover_Binary * moveMaster;
idMover_Binary * activateChain;
int soundPos1;
int sound1to2;
int sound2to1;
int soundPos2;
int soundLoop;
float wait;
float damage;
int duration;
int accelTime;
int decelTime;
idEntityPtr<idEntity> activatedBy;
int stateStartTime;
idStr team;
bool enabled;
int move_thread;
int updateStatus; // 1 = lock behaviour, 2 = open close status
idStrList buddies;
idPhysics_Parametric physicsObj;
qhandle_t areaPortal; // 0 = no portal
bool blocked;
bool playerOnly;
idList< idEntityPtr<idEntity>, TAG_MOVER > guiTargets;
void MatchActivateTeam( moverState_t newstate, int time );
void JoinActivateTeam( idMover_Binary *master );
void UpdateMoverSound( moverState_t state );
void SetMoverState( moverState_t newstate, int time );
moverState_t GetMoverState() const { return moverState; }
void FindGuiTargets();
void SetGuiState( const char *key, const char *val ) const;
void Event_SetCallback();
void Event_ReturnToPos1();
void Event_Use_BinaryMover( idEntity *activator );
void Event_Reached_BinaryMover();
void Event_MatchActivateTeam( moverState_t newstate, int time );
void Event_Enable();
void Event_Disable();
void Event_OpenPortal();
void Event_ClosePortal();
void Event_FindGuiTargets();
void Event_InitGuiTargets();
static void GetMovedir( float dir, idVec3 &movedir );
};
class idDoor : public idMover_Binary {
public:
CLASS_PROTOTYPE( idDoor );
idDoor();
~idDoor();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void Think();
virtual void PreBind();
virtual void PostBind();
virtual void Hide();
virtual void Show();
bool IsOpen();
bool IsNoTouch();
bool AllowPlayerOnly( idEntity *ent );
int IsLocked();
void Lock( int f );
void Use( idEntity *other, idEntity *activator );
void Close();
void Open();
void SetCompanion( idDoor *door );
private:
float triggersize;
bool crusher;
bool noTouch;
bool aas_area_closed;
idStr buddyStr;
idClipModel * trigger;
idClipModel * sndTrigger;
int nextSndTriggerTime;
idVec3 localTriggerOrigin;
idMat3 localTriggerAxis;
idStr requires;
int removeItem;
idStr syncLock;
int normalAxisIndex; // door faces X or Y for spectator teleports
idDoor * companionDoor;
void SetAASAreaState( bool closed );
void GetLocalTriggerPosition( const idClipModel *trigger );
void CalcTriggerBounds( float size, idBounds &bounds );
void Event_Reached_BinaryMover();
void Event_TeamBlocked( idEntity *blockedEntity, idEntity *blockingEntity );
void Event_PartBlocked( idEntity *blockingEntity );
void Event_Touch( idEntity *other, trace_t *trace );
void Event_Activate( idEntity *activator );
void Event_StartOpen();
void Event_SpawnDoorTrigger();
void Event_SpawnSoundTrigger();
void Event_Close();
void Event_Open();
void Event_Lock( int f );
void Event_IsOpen();
void Event_Locked();
void Event_SpectatorTouch( idEntity *other, trace_t *trace );
void Event_OpenPortal();
void Event_ClosePortal();
};
class idPlat : public idMover_Binary {
public:
CLASS_PROTOTYPE( idPlat );
idPlat();
~idPlat();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void RunPhysics_NoBlocking();
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void Think();
virtual void PreBind();
virtual void PostBind();
private:
idClipModel * trigger;
idVec3 localTriggerOrigin;
idMat3 localTriggerAxis;
void GetLocalTriggerPosition( const idClipModel *trigger );
void SpawnPlatTrigger( idVec3 &pos );
void Event_TeamBlocked( idEntity *blockedEntity, idEntity *blockingEntity );
void Event_PartBlocked( idEntity *blockingEntity );
void Event_Touch( idEntity *other, trace_t *trace );
};
/*
===============================================================================
Special periodic movers.
===============================================================================
*/
class idMover_Periodic : public idEntity {
public:
CLASS_PROTOTYPE( idMover_Periodic );
idMover_Periodic();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
protected:
idPhysics_Parametric physicsObj;
float damage;
void Event_TeamBlocked( idEntity *blockedEntity, idEntity *blockingEntity );
void Event_PartBlocked( idEntity *blockingEntity );
};
class idRotater : public idMover_Periodic {
public:
CLASS_PROTOTYPE( idRotater );
idRotater();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
private:
idEntityPtr<idEntity> activatedBy;
void Event_Activate( idEntity *activator );
};
class idBobber : public idMover_Periodic {
public:
CLASS_PROTOTYPE( idBobber );
idBobber();
void Spawn();
private:
};
class idPendulum : public idMover_Periodic {
public:
CLASS_PROTOTYPE( idPendulum );
idPendulum();
void Spawn();
private:
};
class idRiser : public idMover_Periodic {
public:
CLASS_PROTOTYPE( idRiser );
idRiser();
void Spawn();
private:
void Event_Activate( idEntity *activator );
};
#endif /* !__GAME_MOVER_H__ */

3188
neo/d3xp/MultiplayerGame.cpp Normal file

File diff suppressed because it is too large Load Diff

357
neo/d3xp/MultiplayerGame.h Normal file
View File

@@ -0,0 +1,357 @@
/*
===========================================================================
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 __MULTIPLAYERGAME_H__
#define __MULTIPLAYERGAME_H__
/*
===============================================================================
Basic DOOM multiplayer
===============================================================================
*/
class idPlayer;
class idMenuHandler_HUD;
class idMenuHandler_Scoreboard;
class idItemTeam;
enum gameType_t {
GAME_SP = -2,
GAME_RANDOM = -1,
GAME_DM = 0,
GAME_TOURNEY,
GAME_TDM,
GAME_LASTMAN,
GAME_CTF,
GAME_COUNT,
};
// Used by the UI
typedef enum {
FLAGSTATUS_INBASE = 0,
FLAGSTATUS_TAKEN = 1,
FLAGSTATUS_STRAY = 2,
FLAGSTATUS_NONE = 3
} flagStatus_t;
typedef struct mpPlayerState_s {
int ping; // player ping
int fragCount; // kills
int teamFragCount; // team kills
int wins; // wins
bool scoreBoardUp; // toggle based on player scoreboard button, used to activate de-activate the scoreboard gui
int deaths;
} mpPlayerState_t;
const int NUM_CHAT_NOTIFY = 5;
const int CHAT_FADE_TIME = 400;
const int FRAGLIMIT_DELAY = 2000;
const int MP_PLAYER_MINFRAGS = -100;
const int MP_PLAYER_MAXFRAGS = 400; // in CTF frags are player points
const int MP_PLAYER_MAXWINS = 100;
const int MP_PLAYER_MAXPING = 999;
const int MP_CTF_MAXPOINTS = 400;
typedef struct mpChatLine_s {
idStr line;
short fade; // starts high and decreases, line is removed once reached 0
} mpChatLine_t;
typedef enum {
SND_YOUWIN = 0,
SND_YOULOSE,
SND_FIGHT,
SND_THREE,
SND_TWO,
SND_ONE,
SND_SUDDENDEATH,
SND_FLAG_CAPTURED_YOURS,
SND_FLAG_CAPTURED_THEIRS,
SND_FLAG_RETURN,
SND_FLAG_TAKEN_YOURS,
SND_FLAG_TAKEN_THEIRS,
SND_FLAG_DROPPED_YOURS,
SND_FLAG_DROPPED_THEIRS,
SND_COUNT
} snd_evt_t;
class idMultiplayerGame {
public:
idMultiplayerGame();
void Shutdown();
// resets everything and prepares for a match
void Reset();
// setup local data for a new player
void SpawnPlayer( int clientNum );
// checks rules and updates state of the mp game
void Run();
// draws mp hud, scoredboard, etc..
bool Draw( int clientNum );
// updates frag counts and potentially ends the match in sudden death
void PlayerDeath( idPlayer *dead, idPlayer *killer, bool telefrag );
void AddChatLine( VERIFY_FORMAT_STRING const char *fmt, ... );
void WriteToSnapshot( idBitMsg &msg ) const;
void ReadFromSnapshot( const idBitMsg &msg );
// game state
typedef enum {
INACTIVE = 0, // not running
WARMUP, // warming up
COUNTDOWN, // post warmup pre-game
GAMEON, // game is on
SUDDENDEATH, // game is on but in sudden death, first frag wins
GAMEREVIEW, // game is over, scoreboard is up. we wait si_gameReviewPause seconds (which has a min value)
NEXTGAME,
STATE_COUNT
} gameState_t;
static const char *GameStateStrings[ STATE_COUNT ];
idMultiplayerGame::gameState_t GetGameState() const;
static const char *GlobalSoundStrings[ SND_COUNT ];
void PlayGlobalSound( int toPlayerNum, snd_evt_t evt, const char *shader = NULL );
void PlayTeamSound( int toTeam, snd_evt_t evt, const char *shader = NULL ); // sound that's sent only to member of toTeam team
// more compact than a chat line
typedef enum {
MSG_SUICIDE = 0,
MSG_KILLED,
MSG_KILLEDTEAM,
MSG_DIED,
MSG_SUDDENDEATH,
MSG_JOINEDSPEC,
MSG_TIMELIMIT,
MSG_FRAGLIMIT,
MSG_TELEFRAGGED,
MSG_JOINTEAM,
MSG_HOLYSHIT,
MSG_POINTLIMIT,
MSG_FLAGTAKEN,
MSG_FLAGDROP,
MSG_FLAGRETURN,
MSG_FLAGCAPTURE,
MSG_SCOREUPDATE,
MSG_LEFTGAME,
MSG_COUNT
} msg_evt_t;
void PrintMessageEvent( msg_evt_t evt, int parm1 = -1, int parm2 = -1 );
void DisconnectClient( int clientNum );
static void DropWeapon_f( const idCmdArgs &args );
static void MessageMode_f( const idCmdArgs &args );
static void VoiceChat_f( const idCmdArgs &args );
static void VoiceChatTeam_f( const idCmdArgs &args );
int NumActualClients( bool countSpectators, int *teamcount = NULL );
void DropWeapon( int clientNum );
void MapRestart();
void BalanceTeams();
void SwitchToTeam( int clientNum, int oldteam, int newteam );
bool IsPureReady() const;
void ProcessChatMessage( int clientNum, bool team, const char *name, const char *text, const char *sound );
void ProcessVoiceChat( int clientNum, bool team, int index );
bool HandleGuiEvent( const sysEvent_t * sev );
bool IsScoreboardActive();
void SetScoreboardActive( bool active );
void CleanupScoreboard();
void Precache();
void ToggleSpectate();
void GetSpectateText( idPlayer * player, idStr spectatetext[ 2 ], bool scoreboard );
void ClearFrags( int clientNum );
bool CanPlay( idPlayer *p );
bool WantRespawn( idPlayer *p );
void ServerWriteInitialReliableMessages( int clientNum, lobbyUserID_t lobbyUserID );
void ClientReadStartState( const idBitMsg &msg );
void ClientReadWarmupTime( const idBitMsg &msg );
void ClientReadMatchStartedTime( const idBitMsg & msg );
void ClientReadAchievementUnlock( const idBitMsg & msg );
void ServerClientConnect( int clientNum );
int GetFlagPoints( int team ); // Team points in CTF
void SetFlagMsg( bool b ); // allow flag event messages to be sent
bool IsFlagMsgOn(); // should flag event messages go through?
int player_red_flag; // Ent num of red flag carrier for HUD
int player_blue_flag; // Ent num of blue flag carrier for HUD
void PlayerStats( int clientNum, char *data, const int len );
private:
static const char * teamNames[];
static const char * skinNames[];
static const idVec3 skinColors[];
static const int numSkins;
// state vars
gameState_t gameState; // what state the current game is in
gameState_t nextState; // state to switch to when nextStateSwitch is hit
mpPlayerState_t playerState[ MAX_CLIENTS ];
// keep track of clients which are willingly in spectator mode
// time related
int nextStateSwitch; // time next state switch
int warmupEndTime; // warmup till..
int matchStartedTime; // time current match started
// tourney
int currentTourneyPlayer[2];// our current set of players
int lastWinner; // plays again
// warmup
bool one, two, three; // keeps count down voice from repeating
// guis
idMenuHandler_Scoreboard * scoreboardManager;
// chat data
mpChatLine_t chatHistory[ NUM_CHAT_NOTIFY ];
int chatHistoryIndex;
int chatHistorySize; // 0 <= x < NUM_CHAT_NOTIFY
bool chatDataUpdated;
int lastChatLineTime;
// rankings are used by UpdateScoreboard and UpdateHud
int numRankedPlayers; // ranked players, others may be empty slots or spectators
idPlayer * rankedPlayers[MAX_CLIENTS];
bool pureReady; // defaults to false, set to true once server game is running with pure checksums
int fragLimitTimeout;
int voiceChatThrottle;
int startFragLimit; // synchronize to clients in initial state, set on -> GAMEON
idItemTeam * teamFlags[ 2 ];
int teamPoints[ 2 ];
bool flagMsgOn;
private:
void UpdatePlayerRanks();
void GameHasBeenWon();
// updates the passed gui with current score information
void UpdateRankColor( idUserInterface *gui, const char *mask, int i, const idVec3 &vec );
void UpdateScoreboard( idMenuHandler_Scoreboard * scoreboard, idPlayer *owner );
void DrawScoreBoard( idPlayer *player );
void UpdateHud( idPlayer *player, idMenuHandler_HUD * hudManager );
bool Warmup();
idPlayer * FragLimitHit();
idPlayer * FragLeader();
bool TimeLimitHit();
bool PointLimitHit();
// return team with most points
int WinningTeam();
void NewState( gameState_t news, idPlayer *player = NULL );
void UpdateWinsLosses( idPlayer *winner );
// fill any empty tourney slots based on the current tourney ranks
void FillTourneySlots();
void CycleTourneyPlayers();
// walk through the tourneyRank to build a wait list for the clients
void UpdateTourneyLine();
const char * GameTime();
void Clear();
bool EnoughClientsToPlay();
void ClearChatData();
void DrawChat( idPlayer * player );
// go through the clients, and see if they want to be respawned, and if the game allows it
// called during normal gameplay for death -> respawn cycles
// and for a spectator who want back in the game (see param)
void CheckRespawns( idPlayer *spectator = NULL );
// when clients disconnect or join spectate during game, check if we need to end the game
void CheckAbortGame();
void MessageMode( const idCmdArgs &args );
// scores in TDM
void TeamScore( int entityNumber, int team, int delta );
void VoiceChat( const idCmdArgs &args, bool team );
void DumpTourneyLine();
void SuddenRespawn();
void FindTeamFlags();
void NewState_Warmup_ServerAndClient();
void NewState_Countdown_ServerAndClient();
void NewState_GameOn_ServerAndClient();
void NewState_GameReview_ServerAndClient();
public:
const char * GetTeamName( int team ) const;
const char * GetSkinName( int skin ) const;
const idVec3 & GetSkinColor( int skin ) const;
idItemTeam * GetTeamFlag( int team );
flagStatus_t GetFlagStatus( int team );
void TeamScoreCTF( int team, int delta );
void PlayerScoreCTF( int playerIdx, int delta );
// returns entityNum to team flag carrier, -1 if no flag carrier
int GetFlagCarrier( int team );
void UpdateScoreboardFlagStatus();
void ReloadScoreboard();
int GetGameModes( const char *** gameModes, const char *** gameModesDisplay );
bool IsGametypeFlagBased();
bool IsGametypeTeamBased();
};
ID_INLINE idMultiplayerGame::gameState_t idMultiplayerGame::GetGameState() const {
return gameState;
}
ID_INLINE bool idMultiplayerGame::IsPureReady() const {
return pureReady;
}
ID_INLINE void idMultiplayerGame::ClearFrags( int clientNum ) {
playerState[ clientNum ].fragCount = 0;
}
#endif /* !__MULTIPLAYERGAME_H__ */

10742
neo/d3xp/Player.cpp Normal file

File diff suppressed because it is too large Load Diff

924
neo/d3xp/Player.h Normal file
View File

@@ -0,0 +1,924 @@
/*
===========================================================================
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 __GAME_PLAYER_H__
#define __GAME_PLAYER_H__
#include "PredictedValue.h"
/*
===============================================================================
Player entity.
===============================================================================
*/
class idMenuHandler_PDA;
class idMenuHandler_HUD;
class idMenuScreen_HUD;
class idTarget_SetPrimaryObjective;
extern const idEventDef EV_Player_GetButtons;
extern const idEventDef EV_Player_GetMove;
extern const idEventDef EV_Player_GetViewAngles;
extern const idEventDef EV_Player_EnableWeapon;
extern const idEventDef EV_Player_DisableWeapon;
extern const idEventDef EV_Player_ExitTeleporter;
extern const idEventDef EV_Player_SelectWeapon;
extern const idEventDef EV_SpectatorTouch;
const float THIRD_PERSON_FOCUS_DISTANCE = 512.0f;
const int LAND_DEFLECT_TIME = 150;
const int LAND_RETURN_TIME = 300;
const int FOCUS_TIME = 300;
const int FOCUS_GUI_TIME = 500;
const int NUM_QUICK_SLOTS = 4;
const int MAX_WEAPONS = 32;
const int DEAD_HEARTRATE = 0; // fall to as you die
const int LOWHEALTH_HEARTRATE_ADJ = 20; //
const int DYING_HEARTRATE = 30; // used for volumen calc when dying/dead
const int BASE_HEARTRATE = 70; // default
const int ZEROSTAMINA_HEARTRATE = 115; // no stamina
const int MAX_HEARTRATE = 130; // maximum
const int ZERO_VOLUME = -40; // volume at zero
const int DMG_VOLUME = 5; // volume when taking damage
const int DEATH_VOLUME = 15; // volume at death
const int SAVING_THROW_TIME = 5000; // maximum one "saving throw" every five seconds
const int ASYNC_PLAYER_INV_AMMO_BITS = idMath::BitsForInteger( 3000 );
const int ASYNC_PLAYER_INV_CLIP_BITS = -7; // -7 bits to cover the range [-1, 60]
enum gameExpansionType_t {
GAME_BASE,
GAME_D3XP,
GAME_D3LE,
GAME_UNKNOWN
};
struct idObjectiveInfo {
idStr title;
idStr text;
const idMaterial * screenshot;
};
struct idLevelTriggerInfo {
idStr levelName;
idStr triggerName;
};
// powerups - the "type" in item .def must match
enum {
BERSERK = 0,
INVISIBILITY,
MEGAHEALTH,
ADRENALINE,
INVULNERABILITY,
HELLTIME,
ENVIROSUIT,
//HASTE,
ENVIROTIME,
MAX_POWERUPS
};
// powerup modifiers
enum {
SPEED = 0,
PROJECTILE_DAMAGE,
MELEE_DAMAGE,
MELEE_DISTANCE
};
// influence levels
enum {
INFLUENCE_NONE = 0, // none
INFLUENCE_LEVEL1, // no gun or hud
INFLUENCE_LEVEL2, // no gun, hud, movement
INFLUENCE_LEVEL3, // slow player movement
};
typedef struct {
int ammo;
int rechargeTime;
char ammoName[128];
} RechargeAmmo_t;
typedef struct {
char name[64];
idList<int, TAG_IDLIB_LIST_PLAYER> toggleList;
int lastUsed;
} WeaponToggle_t;
class idInventory {
public:
int maxHealth;
int weapons;
int powerups;
int armor;
int maxarmor;
int powerupEndTime[ MAX_POWERUPS ];
RechargeAmmo_t rechargeAmmo[ AMMO_NUMTYPES ];
// mp
int ammoPredictTime; // Unused now but kept for save file compatibility.
int deplete_armor;
float deplete_rate;
int deplete_ammount;
int nextArmorDepleteTime;
int pdasViewed[4]; // 128 bit flags for indicating if a pda has been viewed
int selPDA;
int selEMail;
int selVideo;
int selAudio;
bool pdaOpened;
idList<idDict *> items;
idList<idStr> pdaSecurity;
idList<const idDeclPDA *> pdas;
idList<const idDeclVideo *> videos;
idList<const idDeclEmail *> emails;
bool ammoPulse;
bool weaponPulse;
bool armorPulse;
int lastGiveTime;
idList<idLevelTriggerInfo, TAG_IDLIB_LIST_PLAYER> levelTriggers;
idInventory() { Clear(); }
~idInventory() { Clear(); }
// save games
void Save( idSaveGame *savefile ) const; // archives object for save game file
void Restore( idRestoreGame *savefile ); // unarchives object from save game file
void Clear();
void GivePowerUp( idPlayer *player, int powerup, int msec );
void ClearPowerUps();
void GetPersistantData( idDict &dict );
void RestoreInventory( idPlayer *owner, const idDict &dict );
bool Give( idPlayer *owner, const idDict &spawnArgs, const char *statname, const char *value,
idPredictedValue< int > * idealWeapon, bool updateHud, unsigned int giveFlags );
void Drop( const idDict &spawnArgs, const char *weapon_classname, int weapon_index );
ammo_t AmmoIndexForAmmoClass( const char *ammo_classname ) const;
int MaxAmmoForAmmoClass( const idPlayer *owner, const char *ammo_classname ) const;
int WeaponIndexForAmmoClass( const idDict & spawnArgs, const char *ammo_classname ) const;
ammo_t AmmoIndexForWeaponClass( const char *weapon_classname, int *ammoRequired );
const char * AmmoPickupNameForIndex( ammo_t ammonum ) const;
void AddPickupName( const char * name, idPlayer * owner ); //_D3XP
int HasAmmo( ammo_t type, int amount );
bool UseAmmo( ammo_t type, int amount );
int HasAmmo( const char *weapon_classname, bool includeClip = false, idPlayer* owner = NULL ); // _D3XP
bool HasEmptyClipCannotRefill(const char *weapon_classname, idPlayer* owner);
void UpdateArmor();
void SetInventoryAmmoForType( const int ammoType, const int amount );
void SetClipAmmoForWeapon( const int weapon, const int amount );
int GetInventoryAmmoForType( const int ammoType ) const;
int GetClipAmmoForWeapon( const int weapon ) const;
void WriteAmmoToSnapshot( idBitMsg & msg ) const;
void ReadAmmoFromSnapshot( const idBitMsg & msg, int ownerEntityNumber );
void SetRemoteClientAmmo( const int ownerEntityNumber );
int nextItemPickup;
int nextItemNum;
int onePickupTime;
idList<idStr> pickupItemNames;
idList<idObjectiveInfo> objectiveNames;
void InitRechargeAmmo(idPlayer *owner);
void RechargeAmmo(idPlayer *owner);
bool CanGive( idPlayer *owner, const idDict &spawnArgs, const char *statname, const char *value );
private:
idArray< idPredictedValue< int >, AMMO_NUMTYPES > ammo;
idArray< idPredictedValue< int >, MAX_WEAPONS > clip;
};
typedef struct {
int time;
idVec3 dir; // scaled larger for running
} loggedAccel_t;
typedef struct {
int areaNum;
idVec3 pos;
} aasLocation_t;
class idPlayer : public idActor {
public:
enum {
EVENT_IMPULSE = idEntity::EVENT_MAXEVENTS,
EVENT_EXIT_TELEPORTER,
EVENT_ABORT_TELEPORTER,
EVENT_POWERUP,
EVENT_SPECTATE,
EVENT_PICKUPNAME,
EVENT_FORCE_ORIGIN,
EVENT_KNOCKBACK,
EVENT_MAXEVENTS
};
static const int MAX_PLAYER_PDA = 100;
static const int MAX_PLAYER_VIDEO = 100;
static const int MAX_PLAYER_AUDIO = 100;
static const int MAX_PLAYER_AUDIO_ENTRIES = 2;
usercmd_t oldCmd;
usercmd_t usercmd;
class idPlayerView playerView; // handles damage kicks and effects
renderEntity_t laserSightRenderEntity; // replace crosshair for 3DTV
qhandle_t laserSightHandle;
bool noclip;
bool godmode;
bool spawnAnglesSet; // on first usercmd, we must set deltaAngles
idAngles spawnAngles;
idAngles viewAngles; // player view angles
idAngles cmdAngles; // player cmd angles
float independentWeaponPitchAngle; // viewAngles[PITCH} when head tracking is active
// For interpolating angles between snapshots
idQuat previousViewQuat;
idQuat nextViewQuat;
int buttonMask;
int oldButtons;
int oldImpulseSequence;
int lastHitTime; // last time projectile fired by player hit target
int lastSndHitTime; // MP hit sound - != lastHitTime because we throttle
int lastSavingThrowTime; // for the "free miss" effect
bool pdaHasBeenRead[ MAX_PLAYER_PDA ];
bool videoHasBeenViewed[ MAX_PLAYER_VIDEO ];
bool audioHasBeenHeard[ MAX_PLAYER_AUDIO ][ MAX_PLAYER_AUDIO_ENTRIES ];
idScriptBool AI_FORWARD;
idScriptBool AI_BACKWARD;
idScriptBool AI_STRAFE_LEFT;
idScriptBool AI_STRAFE_RIGHT;
idScriptBool AI_ATTACK_HELD;
idScriptBool AI_WEAPON_FIRED;
idScriptBool AI_JUMP;
idScriptBool AI_CROUCH;
idScriptBool AI_ONGROUND;
idScriptBool AI_ONLADDER;
idScriptBool AI_DEAD;
idScriptBool AI_RUN;
idScriptBool AI_PAIN;
idScriptBool AI_HARDLANDING;
idScriptBool AI_SOFTLANDING;
idScriptBool AI_RELOAD;
idScriptBool AI_TELEPORT;
idScriptBool AI_TURN_LEFT;
idScriptBool AI_TURN_RIGHT;
// inventory
idInventory inventory;
idTarget_SetPrimaryObjective * primaryObjective;
int flashlightBattery;
idEntityPtr<idWeapon> flashlight;
idEntityPtr<idWeapon> weapon;
idMenuHandler_HUD * hudManager;
idMenuScreen_HUD * hud;
idMenuHandler_PDA * pdaMenu;
idSWF * mpMessages;
bool objectiveSystemOpen;
int quickSlot[ NUM_QUICK_SLOTS ];
int weapon_soulcube;
int weapon_pda;
int weapon_fists;
int weapon_flashlight;
int weapon_chainsaw;
int weapon_bloodstone;
int weapon_bloodstone_active1;
int weapon_bloodstone_active2;
int weapon_bloodstone_active3;
bool harvest_lock;
int heartRate;
idInterpolate<float> heartInfo;
int lastHeartAdjust;
int lastHeartBeat;
int lastDmgTime;
int deathClearContentsTime;
bool doingDeathSkin;
int lastArmorPulse; // lastDmgTime if we had armor at time of hit
float stamina;
float healthPool; // amount of health to give over time
int nextHealthPulse;
bool healthPulse;
bool healthTake;
int nextHealthTake;
//-----------------------------------------------------------------
// controller shake parms
//-----------------------------------------------------------------
const static int MAX_SHAKE_BUFFER = 3;
float controllerShakeHighMag[ MAX_SHAKE_BUFFER ]; // magnitude of the high frequency controller shake
float controllerShakeLowMag[ MAX_SHAKE_BUFFER ]; // magnitude of the low frequency controller shake
int controllerShakeHighTime[ MAX_SHAKE_BUFFER ]; // time the controller shake ends for high frequency.
int controllerShakeLowTime[ MAX_SHAKE_BUFFER ]; // time the controller shake ends for low frequency.
int controllerShakeTimeGroup;
bool hiddenWeapon; // if the weapon is hidden ( in noWeapons maps )
idEntityPtr<idProjectile> soulCubeProjectile;
idAimAssist aimAssist;
int spectator;
bool forceScoreBoard;
bool forceRespawn;
bool spectating;
int lastSpectateTeleport;
bool lastHitToggle;
bool wantSpectate; // from userInfo
bool weaponGone; // force stop firing
bool useInitialSpawns; // toggled by a map restart to be active for the first game spawn
int tourneyRank; // for tourney cycling - the higher, the more likely to play next - server
int tourneyLine; // client side - our spot in the wait line. 0 means no info.
int spawnedTime; // when client first enters the game
bool carryingFlag; // is the player carrying the flag?
idEntityPtr<idEntity> teleportEntity; // while being teleported, this is set to the entity we'll use for exit
int teleportKiller; // entity number of an entity killing us at teleporter exit
bool lastManOver; // can't respawn in last man anymore (srv only)
bool lastManPlayAgain; // play again when end game delay is cancelled out before expiring (srv only)
bool lastManPresent; // true when player was in when game started (spectators can't join a running LMS)
bool isLagged; // replicated from server, true if packets haven't been received from client.
int isChatting; // replicated from server, true if the player is chatting.
// timers
int minRespawnTime; // can respawn when time > this, force after g_forcerespawn
int maxRespawnTime; // force respawn after this time
// the first person view values are always calculated, even
// if a third person view is used
idVec3 firstPersonViewOrigin;
idMat3 firstPersonViewAxis;
idDragEntity dragEntity;
idFuncMountedObject * mountedObject;
idEntityPtr<idLight> enviroSuitLight;
bool healthRecharge;
int lastHealthRechargeTime;
int rechargeSpeed;
float new_g_damageScale;
bool bloomEnabled;
float bloomSpeed;
float bloomIntensity;
public:
CLASS_PROTOTYPE( idPlayer );
idPlayer();
virtual ~idPlayer();
void Spawn();
void Think();
void UpdateLaserSight();
// save games
void Save( idSaveGame *savefile ) const; // archives object for save game file
void Restore( idRestoreGame *savefile ); // unarchives object from save game file
virtual void Hide();
virtual void Show();
void Init();
void PrepareForRestart();
virtual void Restart();
void LinkScriptVariables();
void SetupWeaponEntity();
void SelectInitialSpawnPoint( idVec3 &origin, idAngles &angles );
void SpawnFromSpawnSpot();
void SpawnToPoint( const idVec3 &spawn_origin, const idAngles &spawn_angles );
void SetClipModel(); // spectator mode uses a different bbox size
void SavePersistantInfo();
void RestorePersistantInfo();
void SetLevelTrigger( const char *levelName, const char *triggerName );
void CacheWeapons();
void EnterCinematic();
void ExitCinematic();
void UpdateConditions();
void SetViewAngles( const idAngles &angles );
// Controller Shake
void ControllerShakeFromDamage( int damage );
void SetControllerShake( float highMagnitude, int highDuration, float lowMagnitude, int lowDuration );
void ResetControllerShake();
void GetControllerShake( int & highMagnitude, int & lowMagnitude ) const;
idAimAssist * GetAimAssist() { return &aimAssist; }
// delta view angles to allow movers to rotate the view of the player
void UpdateDeltaViewAngles( const idAngles &angles );
virtual bool Collide( const trace_t &collision, const idVec3 &velocity );
virtual void GetAASLocation( idAAS *aas, idVec3 &pos, int &areaNum ) const;
virtual void GetAIAimTargets( const idVec3 &lastSightPos, idVec3 &headPos, idVec3 &chestPos );
virtual void DamageFeedback( idEntity *victim, idEntity *inflictor, int &damage );
void CalcDamagePoints( idEntity *inflictor, idEntity *attacker, const idDict *damageDef,
const float damageScale, const int location, int *health, int *armor );
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location );
// New damage path for instant client feedback.
void ServerDealDamage( int damage, idEntity & inflictor, idEntity & attacker, const idVec3 & dir, const char * damageDefName, const int location ); // Actually updates the player's health independent of feedback.
int AdjustDamageAmount( const int inputDamage );
// use exitEntityNum to specify a teleport with private camera view and delayed exit
virtual void Teleport( const idVec3 &origin, const idAngles &angles, idEntity *destination );
void Kill( bool delayRespawn, bool nodamage );
virtual void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
void StartFxOnBone(const char *fx, const char *bone);
renderView_t * GetRenderView();
void CalculateRenderView(); // called every tic by player code
void CalculateFirstPersonView();
void AddChatMessage( int index, int alpha, const idStr & message );
void UpdateSpectatingText();
void ClearChatMessage( int index );
void DrawHUD( idMenuHandler_HUD * hudManager );
void WeaponFireFeedback( const idDict *weaponDef );
float DefaultFov() const;
float CalcFov( bool honorZoom );
void CalculateViewWeaponPos( idVec3 &origin, idMat3 &axis );
idVec3 GetEyePosition() const;
void GetViewPos( idVec3 &origin, idMat3 &axis ) const;
void OffsetThirdPersonView( float angle, float range, float height, bool clip );
bool Give( const char *statname, const char *value, unsigned int giveFlags );
bool GiveItem( idItem *item, unsigned int giveFlags );
void GiveItem( const char *name );
void GiveHealthPool( float amt );
void SetPrimaryObjective( idTarget_SetPrimaryObjective * target ) { primaryObjective = target; }
idTarget_SetPrimaryObjective * GetPrimaryObjective() { return primaryObjective; }
idInventory & GetInventory() { return inventory; }
bool GiveInventoryItem( idDict *item, unsigned int giveFlags );
void RemoveInventoryItem( idDict *item );
bool GiveInventoryItem( const char *name );
void RemoveInventoryItem( const char *name );
idDict * FindInventoryItem( const char *name );
idDict * FindInventoryItem( int index );
int GetNumInventoryItems();
void PlayAudioLog( const idSoundShader * sound );
void EndAudioLog();
void PlayVideoDisk( const idDeclVideo * decl );
void EndVideoDisk();
const idMaterial * GetVideoMaterial() { return pdaVideoMat; }
void SetQuickSlot( int index, int val );
int GetQuickSlot( int index );
void GivePDA( const idDeclPDA * pda, const char * securityItem );
void GiveVideo( const idDeclVideo * video, const char * itemName );
void GiveEmail( const idDeclEmail * email );
void GiveSecurity( const char * security );
void GiveObjective( const char * title, const char * text, const idMaterial * screenshot );
void CompleteObjective( const char * title );
bool GivePowerUp( int powerup, int time, unsigned int giveFlags );
void ClearPowerUps();
bool PowerUpActive( int powerup ) const;
float PowerUpModifier( int type );
int SlotForWeapon( const char *weaponName );
void Reload();
void NextWeapon();
void NextBestWeapon();
void PrevWeapon();
void SetPreviousWeapon( int num ) { previousWeapon = num; }
void SelectWeapon( int num, bool force );
void DropWeapon( bool died ) ;
void StealWeapon( idPlayer *player );
void AddProjectilesFired( int count );
void AddProjectileHits( int count );
void SetLastHitTime( int time );
void LowerWeapon();
void RaiseWeapon();
void WeaponLoweringCallback();
void WeaponRisingCallback();
void RemoveWeapon( const char *weap );
void RemoveAllButEssentialWeapons();
bool CanShowWeaponViewmodel() const;
void AddAIKill();
void SetSoulCubeProjectile( idProjectile *projectile );
void AdjustHeartRate( int target, float timeInSecs, float delay, bool force );
void SetCurrentHeartRate();
int GetBaseHeartRate();
void UpdateAir();
void UpdatePowerupHud();
virtual bool HandleSingleGuiCommand( idEntity *entityGui, idLexer *src );
bool GuiActive() { return focusGUIent != NULL; }
bool HandleGuiEvents( const sysEvent_t * ev );
void PerformImpulse( int impulse );
void Spectate( bool spectate, bool force = false );
void TogglePDA();
void RouteGuiMouse( idUserInterface *gui );
void UpdateHud();
const idDeclPDA * GetPDA() const;
bool GetPDAOpen() const { return objectiveSystemOpen; }
const idDeclVideo * GetVideo( int index );
void SetInfluenceFov( float fov );
void SetInfluenceView( const char *mtr, const char *skinname, float radius, idEntity *ent );
void SetInfluenceLevel( int level );
int GetInfluenceLevel() { return influenceActive; };
void SetPrivateCameraView( idCamera *camView );
idCamera * GetPrivateCameraView() const { return privateCameraView; }
void StartFxFov( float duration );
void UpdateHudWeapon( bool flashWeapon = true );
void UpdateChattingHud();
void UpdateHudStats( idMenuHandler_HUD * hudManager );
void Event_StopAudioLog();
bool IsSoundChannelPlaying( const s_channelType channel = SND_CHANNEL_ANY );
void ShowTip( const char *title, const char *tip, bool autoHide );
void HideTip();
bool IsTipVisible() { return tipUp; };
void HideObjective();
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
void WritePlayerStateToSnapshot( idBitMsg &msg ) const;
void ReadPlayerStateFromSnapshot( const idBitMsg &msg );
virtual bool ServerReceiveEvent( int event, int time, const idBitMsg &msg );
virtual bool GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis );
virtual bool GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis );
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
bool IsRespawning();
bool IsInTeleport();
int GetSkinIndex() const { return skinIndex; }
idEntity *GetInfluenceEntity() { return influenceEntity; };
const idMaterial *GetInfluenceMaterial() { return influenceMaterial; };
float GetInfluenceRadius() { return influenceRadius; };
// server side work for in/out of spectate. takes care of spawning it into the world as well
void ServerSpectate( bool spectate );
// for very specific usage. != GetPhysics()
idPhysics *GetPlayerPhysics();
void TeleportDeath( int killer );
void SetLeader( bool lead );
bool IsLeader();
void UpdateSkinSetup();
bool OnLadder() const;
virtual void UpdatePlayerIcons();
virtual void DrawPlayerIcons();
virtual void HidePlayerIcons();
bool NeedsIcon();
void StartHealthRecharge(int speed);
void StopHealthRecharge();
idStr GetCurrentWeapon();
int GetCurrentWeaponSlot() { return currentWeapon; }
int GetIdealWeapon() { return idealWeapon.Get(); }
idHashTable<WeaponToggle_t> GetWeaponToggles() const { return weaponToggles; }
bool CanGive( const char *statname, const char *value );
void StopHelltime( bool quick = true );
void PlayHelltimeStopSound();
void DropFlag(); // drop CTF item
void ReturnFlag();
virtual void FreeModelDef();
bool SelfSmooth();
void SetSelfSmooth( bool b );
const idAngles & GetViewBobAngles() { return viewBobAngles; }
const idVec3 & GetViewBob() { return viewBob; }
idAchievementManager & GetAchievementManager() { return achievementManager; }
const idAchievementManager & GetAchievementManager() const { return achievementManager; }
int GetPlayedTime() const { return playedTimeSecs; }
void HandleUserCmds( const usercmd_t & newcmd );
int GetClientFireCount() const { return clientFireCount; }
void IncrementFireCount() { ++clientFireCount; }
void ShowRespawnHudMessage();
void HideRespawnHudMessage();
bool IsLocallyControlled() const { return entityNumber == gameLocal.GetLocalClientNum(); }
gameExpansionType_t GetExpansionType() const;
void AddProjectileKills() { numProjectileKills++; }
int GetProjectileKills() const { return numProjectileKills; }
void ResetProjectileKills() { numProjectileKills = 0; }
private:
// Stats & achievements
idAchievementManager achievementManager;
int playedTimeSecs;
int playedTimeResidual;
jointHandle_t hipJoint;
jointHandle_t chestJoint;
jointHandle_t headJoint;
idPhysics_Player physicsObj; // player physics
idList<aasLocation_t, TAG_IDLIB_LIST_PLAYER> aasLocation; // for AI tracking the player
int bobFoot;
float bobFrac;
float bobfracsin;
int bobCycle; // for view bobbing and footstep generation
float xyspeed;
int stepUpTime;
float stepUpDelta;
float idealLegsYaw;
float legsYaw;
bool legsForward;
float oldViewYaw;
idAngles viewBobAngles;
idVec3 viewBob;
int landChange;
int landTime;
int currentWeapon;
idPredictedValue< int > idealWeapon;
int previousWeapon;
int weaponSwitchTime;
bool weaponEnabled;
int skinIndex;
const idDeclSkin * skin;
const idDeclSkin * powerUpSkin;
int numProjectilesFired; // number of projectiles fired
int numProjectileHits; // number of hits on mobs
int numProjectileKills; // number of kills with a projectile.
bool airless;
int airMsec; // set to pm_airMsec at start, drops in vacuum
int lastAirDamage;
bool gibDeath;
bool gibsLaunched;
idVec3 gibsDir;
idInterpolate<float> zoomFov;
idInterpolate<float> centerView;
bool fxFov;
float influenceFov;
int influenceActive; // level of influence.. 1 == no gun or hud .. 2 == 1 + no movement
idEntity * influenceEntity;
const idMaterial * influenceMaterial;
float influenceRadius;
const idDeclSkin * influenceSkin;
idCamera * privateCameraView;
static const int NUM_LOGGED_VIEW_ANGLES = 64; // for weapon turning angle offsets
idAngles loggedViewAngles[NUM_LOGGED_VIEW_ANGLES]; // [gameLocal.framenum&(LOGGED_VIEW_ANGLES-1)]
static const int NUM_LOGGED_ACCELS = 16; // for weapon turning angle offsets
loggedAccel_t loggedAccel[NUM_LOGGED_ACCELS]; // [currentLoggedAccel & (NUM_LOGGED_ACCELS-1)]
int currentLoggedAccel;
// if there is a focusGUIent, the attack button will be changed into mouse clicks
idEntity * focusGUIent;
idUserInterface * focusUI; // focusGUIent->renderEntity.gui, gui2, or gui3
idAI * focusCharacter;
int talkCursor; // show the state of the focusCharacter (0 == can't talk/dead, 1 == ready to talk, 2 == busy talking)
int focusTime;
idAFEntity_Vehicle * focusVehicle;
idUserInterface * cursor;
// full screen guis track mouse movements directly
int oldMouseX;
int oldMouseY;
const idMaterial * pdaVideoMat;
bool tipUp;
bool objectiveUp;
int lastDamageDef;
idVec3 lastDamageDir;
int lastDamageLocation;
int smoothedFrame;
bool smoothedOriginUpdated;
idVec3 smoothedOrigin;
idAngles smoothedAngles;
idHashTable<WeaponToggle_t> weaponToggles;
int hudPowerup;
int lastHudPowerup;
int hudPowerupDuration;
// mp
bool respawning; // set to true while in SpawnToPoint for telefrag checks
bool leader; // for sudden death situations
int lastSpectateChange;
int lastTeleFX;
bool weaponCatchup; // raise up the weapon silently ( state catchups )
int MPAim; // player num in aim
int lastMPAim;
int lastMPAimTime; // last time the aim changed
int MPAimFadeTime; // for GUI fade
bool MPAimHighlight;
bool isTelefragged; // proper obituaries
int serverOverridePositionTime;
int clientFireCount;
idPlayerIcon playerIcon;
bool selfSmooth;
netBoolEvent_t respawn_netEvent;
void LookAtKiller( idEntity *inflictor, idEntity *attacker );
void StopFiring();
void FireWeapon();
void Weapon_Combat();
void Weapon_NPC();
void Weapon_GUI();
void UpdateWeapon();
void UpdateFlashlight();
void FlashlightOn();
void FlashlightOff();
void UpdateSpectating();
void SpectateFreeFly( bool force ); // ignore the timeout to force when followed spec is no longer valid
void SpectateCycle();
idAngles GunTurningOffset();
idVec3 GunAcceleratingOffset();
void UseObjects();
void CrashLand( const idVec3 &oldOrigin, const idVec3 &oldVelocity );
void BobCycle( const idVec3 &pushVelocity );
void UpdateViewAngles();
void EvaluateControls();
void AdjustSpeed();
void AdjustBodyAngles();
void InitAASLocation();
void SetAASLocation();
void Move();
void Move_Interpolated( float fraction );
void RunPhysics_RemoteClientCorrection();
void UpdatePowerUps();
void UpdateDeathSkin( bool state_hitch );
void ClearPowerup( int i );
void SetSpectateOrigin();
bool AllowClientAuthPhysics();
virtual int GetPhysicsTimeStep() const;
void ClearFocus();
void UpdateFocus();
void UpdateLocation();
idUserInterface * ActiveGui();
// mp
void Respawn_Shared();
bool WeaponAvailable( const char* name );
void UseVehicle();
void Event_GetButtons();
void Event_GetMove();
void Event_GetViewAngles();
void Event_StopFxFov();
void Event_EnableWeapon();
void Event_DisableWeapon();
void Event_GetCurrentWeapon();
void Event_GetPreviousWeapon();
void Event_SelectWeapon( const char *weaponName );
void Event_GetWeaponEntity();
void Event_OpenPDA();
void Event_PDAAvailable();
void Event_InPDA();
void Event_ExitTeleporter();
void Event_HideTip();
void Event_LevelTrigger();
void Event_Gibbed();
void Event_ForceOrigin( idVec3 & origin, idAngles & angles );
void Event_GiveInventoryItem( const char* name );
void Event_RemoveInventoryItem( const char* name );
void Event_GetIdealWeapon();
void Event_WeaponAvailable( const char* name );
void Event_SetPowerupTime( int powerup, int time );
void Event_IsPowerupActive( int powerup );
void Event_StartWarp();
void Event_StopHelltime( int mode );
void Event_ToggleBloom( int on );
void Event_SetBloomParms( float speed, float intensity );
};
ID_INLINE bool idPlayer::IsRespawning() {
return respawning;
}
ID_INLINE idPhysics* idPlayer::GetPlayerPhysics() {
return &physicsObj;
}
ID_INLINE bool idPlayer::IsInTeleport() {
return ( teleportEntity.GetEntity() != NULL );
}
ID_INLINE void idPlayer::SetLeader( bool lead ) {
leader = lead;
}
ID_INLINE bool idPlayer::IsLeader() {
return leader;
}
ID_INLINE bool idPlayer::SelfSmooth() {
return selfSmooth;
}
ID_INLINE void idPlayer::SetSelfSmooth( bool b ) {
selfSmooth = b;
}
extern idCVar g_infiniteAmmo;
#endif /* !__GAME_PLAYER_H__ */

190
neo/d3xp/PlayerIcon.cpp Normal file
View File

@@ -0,0 +1,190 @@
/*
===========================================================================
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.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
#include "PlayerIcon.h"
static const char * iconKeys[ ICON_NONE ] = {
"mtr_icon_lag",
"mtr_icon_chat"
,"mtr_icon_redteam",
"mtr_icon_blueteam"
};
/*
===============
idPlayerIcon::idPlayerIcon
===============
*/
idPlayerIcon::idPlayerIcon() {
iconHandle = -1;
iconType = ICON_NONE;
}
/*
===============
idPlayerIcon::~idPlayerIcon
===============
*/
idPlayerIcon::~idPlayerIcon() {
FreeIcon();
}
/*
===============
idPlayerIcon::Draw
===============
*/
void idPlayerIcon::Draw( idPlayer *player, jointHandle_t joint ) {
idVec3 origin;
idMat3 axis;
if ( joint == INVALID_JOINT ) {
FreeIcon();
return;
}
player->GetJointWorldTransform( joint, gameLocal.time, origin, axis );
origin.z += 16.0f;
Draw( player, origin );
}
/*
===============
idPlayerIcon::Draw
===============
*/
void idPlayerIcon::Draw( idPlayer *player, const idVec3 &origin ) {
idPlayer *localPlayer = gameLocal.GetLocalPlayer();
if ( !localPlayer || !localPlayer->GetRenderView() ) {
FreeIcon();
return;
}
idMat3 axis = localPlayer->GetRenderView()->viewaxis;
if ( player->isLagged && !player->spectating ) {
// create the icon if necessary, or update if already created
if ( !CreateIcon( player, ICON_LAG, origin, axis ) ) {
UpdateIcon( player, origin, axis );
}
} else if ( g_CTFArrows.GetBool() && gameLocal.mpGame.IsGametypeFlagBased() && gameLocal.GetLocalPlayer() && player->team == gameLocal.GetLocalPlayer()->team && !player->IsHidden() && !player->AI_DEAD ) {
int icon = ICON_TEAM_RED + player->team;
if ( icon != ICON_TEAM_RED && icon != ICON_TEAM_BLUE )
return;
if ( !CreateIcon( player, ( playerIconType_t )icon, origin, axis ) ) {
UpdateIcon( player, origin, axis );
}
} else {
FreeIcon();
}
}
/*
===============
idPlayerIcon::FreeIcon
===============
*/
void idPlayerIcon::FreeIcon() {
if ( iconHandle != - 1 ) {
gameRenderWorld->FreeEntityDef( iconHandle );
iconHandle = -1;
}
iconType = ICON_NONE;
}
/*
===============
idPlayerIcon::CreateIcon
===============
*/
bool idPlayerIcon::CreateIcon( idPlayer *player, playerIconType_t type, const idVec3 &origin, const idMat3 &axis ) {
assert( type < ICON_NONE );
const char *mtr = player->spawnArgs.GetString( iconKeys[ type ], "_default" );
return CreateIcon( player, type, mtr, origin, axis );
}
/*
===============
idPlayerIcon::CreateIcon
===============
*/
bool idPlayerIcon::CreateIcon( idPlayer *player, playerIconType_t type, const char *mtr, const idVec3 &origin, const idMat3 &axis ) {
assert( type != ICON_NONE );
if ( type == iconType ) {
return false;
}
FreeIcon();
memset( &renderEnt, 0, sizeof( renderEnt ) );
renderEnt.origin = origin;
renderEnt.axis = axis;
renderEnt.shaderParms[ SHADERPARM_RED ] = 1.0f;
renderEnt.shaderParms[ SHADERPARM_GREEN ] = 1.0f;
renderEnt.shaderParms[ SHADERPARM_BLUE ] = 1.0f;
renderEnt.shaderParms[ SHADERPARM_ALPHA ] = 1.0f;
renderEnt.shaderParms[ SHADERPARM_SPRITE_WIDTH ] = 16.0f;
renderEnt.shaderParms[ SHADERPARM_SPRITE_HEIGHT ] = 16.0f;
renderEnt.hModel = renderModelManager->FindModel( "_sprite" );
renderEnt.callback = NULL;
renderEnt.numJoints = 0;
renderEnt.joints = NULL;
renderEnt.customSkin = 0;
renderEnt.noShadow = true;
renderEnt.noSelfShadow = true;
renderEnt.customShader = declManager->FindMaterial( mtr );
renderEnt.referenceShader = 0;
renderEnt.bounds = renderEnt.hModel->Bounds( &renderEnt );
iconHandle = gameRenderWorld->AddEntityDef( &renderEnt );
iconType = type;
return true;
}
/*
===============
idPlayerIcon::UpdateIcon
===============
*/
void idPlayerIcon::UpdateIcon( idPlayer *player, const idVec3 &origin, const idMat3 &axis ) {
assert( iconHandle >= 0 );
renderEnt.origin = origin;
renderEnt.axis = axis;
gameRenderWorld->UpdateEntityDef( iconHandle, &renderEnt );
}

65
neo/d3xp/PlayerIcon.h Normal file
View File

@@ -0,0 +1,65 @@
/*
===========================================================================
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 __PLAYERICON_H__
#define __PLAYERICON_H__
typedef enum {
ICON_LAG,
ICON_CHAT,
ICON_TEAM_RED,
ICON_TEAM_BLUE,
ICON_NONE
} playerIconType_t;
class idPlayerIcon {
public:
public:
idPlayerIcon();
~idPlayerIcon();
void Draw( idPlayer *player, jointHandle_t joint );
void Draw( idPlayer *player, const idVec3 &origin );
public:
playerIconType_t iconType;
renderEntity_t renderEnt;
qhandle_t iconHandle;
public:
void FreeIcon();
bool CreateIcon( idPlayer* player, playerIconType_t type, const char *mtr, const idVec3 &origin, const idMat3 &axis );
bool CreateIcon( idPlayer* player, playerIconType_t type, const idVec3 &origin, const idMat3 &axis );
void UpdateIcon( idPlayer* player, const idVec3 &origin, const idMat3 &axis );
};
#endif /* !_PLAYERICON_H_ */

1749
neo/d3xp/PlayerView.cpp Normal file

File diff suppressed because it is too large Load Diff

417
neo/d3xp/PlayerView.h Normal file
View File

@@ -0,0 +1,417 @@
/*
===========================================================================
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 __GAME_PLAYERVIEW_H__
#define __GAME_PLAYERVIEW_H__
class idMenuHandler_HUD;
/*
===============================================================================
Player view.
===============================================================================
*/
// screenBlob_t are for the on-screen damage claw marks, etc
typedef struct {
const idMaterial * material;
float x, y, w, h;
float s1, t1, s2, t2;
int finishTime;
int startFadeTime;
float driftAmount;
} screenBlob_t;
#define MAX_SCREEN_BLOBS 8
class WarpPolygon_t {
public:
idVec4 outer1;
idVec4 outer2;
idVec4 center;
};
class Warp_t {
public:
int id;
bool active;
int startTime;
float initialRadius;
idVec3 worldOrigin;
idVec2 screenOrigin;
int durationMsec;
idList<WarpPolygon_t, TAG_IDLIB_LIST_PLAYER> polys;
};
class idPlayerView;
class FullscreenFXManager;
/*
==================
FxFader
==================
*/
class FxFader {
enum {
FX_STATE_OFF,
FX_STATE_RAMPUP,
FX_STATE_RAMPDOWN,
FX_STATE_ON
};
int time;
int state;
float alpha;
int msec;
public:
FxFader();
// primary functions
bool SetTriggerState( bool active );
virtual void Save( idSaveGame *savefile );
virtual void Restore( idRestoreGame *savefile );
// fader functions
void SetFadeTime( int t ) { msec = t; };
int GetFadeTime() { return msec; };
// misc functions
float GetAlpha() { return alpha; };
};
/*
==================
FullscreenFX
==================
*/
class FullscreenFX {
protected:
idStr name;
FxFader fader;
FullscreenFXManager *fxman;
public:
FullscreenFX() { fxman = NULL; };
virtual ~FullscreenFX() { };
virtual void Initialize() = 0;
virtual bool Active() = 0;
virtual void HighQuality() = 0;
virtual void LowQuality() { };
virtual void AccumPass( const renderView_t *view ) { };
virtual bool HasAccum() { return false; };
void SetName( idStr n ) { name = n; };
idStr GetName() { return name; };
void SetFXManager( FullscreenFXManager *fx ) { fxman = fx; };
bool SetTriggerState( bool state ) { return fader.SetTriggerState( state ); };
void SetFadeSpeed( int msec ) { fader.SetFadeTime( msec ); };
float GetFadeAlpha() { return fader.GetAlpha(); };
virtual void Save( idSaveGame *savefile );
virtual void Restore( idRestoreGame *savefile );
};
/*
==================
FullscreenFX_Helltime
==================
*/
class FullscreenFX_Helltime : public FullscreenFX {
const idMaterial * initMaterial;
const idMaterial * captureMaterials[3];
const idMaterial * drawMaterial;
bool clearAccumBuffer;
int DetermineLevel();
public:
virtual void Initialize();
virtual bool Active();
virtual void HighQuality();
virtual void AccumPass( const renderView_t *view );
virtual bool HasAccum() { return true; };
virtual void Restore( idRestoreGame *savefile );
};
/*
==================
FullscreenFX_Multiplayer
==================
*/
class FullscreenFX_Multiplayer : public FullscreenFX {
const idMaterial * initMaterial;
const idMaterial * captureMaterial;
const idMaterial * drawMaterial;
bool clearAccumBuffer;
int DetermineLevel();
public:
virtual void Initialize();
virtual bool Active();
virtual void HighQuality();
virtual void AccumPass( const renderView_t *view );
virtual bool HasAccum() { return true; };
virtual void Restore( idRestoreGame *savefile );
};
/*
==================
FullscreenFX_Warp
==================
*/
class FullscreenFX_Warp : public FullscreenFX {
const idMaterial* material;
bool grabberEnabled;
int startWarpTime;
void DrawWarp( WarpPolygon_t wp, float interp );
public:
virtual void Initialize();
virtual bool Active();
virtual void HighQuality();
void EnableGrabber( bool active ) { grabberEnabled = active; startWarpTime = gameLocal.slow.time; };
virtual void Save( idSaveGame *savefile );
virtual void Restore( idRestoreGame *savefile );
};
/*
==================
FullscreenFX_EnviroSuit
==================
*/
class FullscreenFX_EnviroSuit : public FullscreenFX {
const idMaterial* material;
public:
virtual void Initialize();
virtual bool Active();
virtual void HighQuality();
};
/*
==================
FullscreenFX_DoubleVision
==================
*/
class FullscreenFX_DoubleVision : public FullscreenFX {
const idMaterial* material;
public:
virtual void Initialize();
virtual bool Active();
virtual void HighQuality();
};
/*
==================
FullscreenFX_InfluenceVision
==================
*/
class FullscreenFX_InfluenceVision : public FullscreenFX {
public:
virtual void Initialize();
virtual bool Active();
virtual void HighQuality();
};
/*
==================
FullscreenFX_Bloom
==================
*/
class FullscreenFX_Bloom : public FullscreenFX {
const idMaterial* drawMaterial;
const idMaterial* initMaterial;
float currentIntensity;
float targetIntensity;
public:
virtual void Initialize();
virtual bool Active();
virtual void HighQuality();
virtual void Save( idSaveGame *savefile );
virtual void Restore( idRestoreGame *savefile );
};
/*
==================
FullscreenFXManager
==================
*/
class FullscreenFXManager {
idList<FullscreenFX*, TAG_FX> fx;
idPlayerView * playerView;
const idMaterial* blendBackMaterial;
void CreateFX( idStr name, idStr fxtype, int fade );
public:
FullscreenFXManager();
virtual ~FullscreenFXManager();
void Initialize( idPlayerView *pv );
void Process( const renderView_t *view );
void Blendback( float alpha );
idPlayerView* GetPlayerView() { return playerView; };
idPlayer* GetPlayer() { return gameLocal.GetLocalPlayer(); };
int GetNum() { return fx.Num(); };
FullscreenFX* GetFX( int index ) { return fx[index]; };
FullscreenFX* FindFX( idStr name );
void Save( idSaveGame *savefile );
void Restore( idRestoreGame *savefile );
};
class idPlayerView {
public:
idPlayerView();
~idPlayerView();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void SetPlayerEntity( class idPlayer *playerEnt );
void ClearEffects();
void DamageImpulse( idVec3 localKickDir, const idDict *damageDef );
void WeaponFireFeedback( const idDict *weaponDef );
idAngles AngleOffset() const; // returns the current kick angle
idMat3 ShakeAxis() const; // returns the current shake angle
void CalculateShake();
// this may involve rendering to a texture and displaying
// that with a warp model or in double vision mode
void RenderPlayerView( idMenuHandler_HUD * hudManager );
void EmitStereoEyeView( const int eye, idMenuHandler_HUD * hudManager );
void Fade( idVec4 color, int time );
void Flash( idVec4 color, int time );
// temp for view testing
void EnableBFGVision( bool b ) { bfgVision = b; };
private:
void SingleView( const renderView_t *view, idMenuHandler_HUD * hudManager );
void ScreenFade();
screenBlob_t * GetScreenBlob();
screenBlob_t screenBlobs[MAX_SCREEN_BLOBS];
public:
int dvFinishTime; // double vision will be stopped at this time
int kickFinishTime; // view kick will be stopped at this time
idAngles kickAngles;
bool bfgVision; //
const idMaterial * tunnelMaterial; // health tunnel vision
const idMaterial * armorMaterial; // armor damage view effect
const idMaterial * berserkMaterial; // berserk effect
const idMaterial * irGogglesMaterial; // ir effect
const idMaterial * bloodSprayMaterial; // blood spray
const idMaterial * bfgMaterial; // when targeted with BFG
float lastDamageTime; // accentuate the tunnel effect for a while
idVec4 fadeColor; // fade color
idVec4 fadeToColor; // color to fade to
idVec4 fadeFromColor; // color to fade from
float fadeRate; // fade rate
int fadeTime; // fade time
idAngles shakeAng; // from the sound sources
idPlayer * player;
renderView_t view;
FullscreenFXManager *fxManager;
public:
int AddWarp( idVec3 worldOrigin, float centerx, float centery, float initialRadius, float durationMsec );
void FreeWarp( int id );
};
// the crosshair is swapped for a laser sight in stereo rendering
bool IsGameStereoRendered();
#endif /* !__GAME_PLAYERVIEW_H__ */

78
neo/d3xp/PredictedValue.h Normal file
View File

@@ -0,0 +1,78 @@
/*
===========================================================================
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

View File

@@ -0,0 +1,220 @@
/*
===========================================================================
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

2989
neo/d3xp/Projectile.cpp Normal file

File diff suppressed because it is too large Load Diff

339
neo/d3xp/Projectile.h Normal file
View File

@@ -0,0 +1,339 @@
/*
===========================================================================
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 __GAME_PROJECTILE_H__
#define __GAME_PROJECTILE_H__
/*
===============================================================================
idProjectile
===============================================================================
*/
extern const idEventDef EV_Explode;
class idProjectile : public idEntity {
public :
CLASS_PROTOTYPE( idProjectile );
idProjectile();
virtual ~idProjectile();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Create( idEntity *owner, const idVec3 &start, const idVec3 &dir );
virtual void Launch( const idVec3 &start, const idVec3 &dir, const idVec3 &pushVelocity, const float timeSinceFire = 0.0f, const float launchPower = 1.0f, const float dmgPower = 1.0f );
virtual void FreeLightDef();
idEntity * GetOwner() const;
void CatchProjectile( idEntity* o, const char* reflectName );
int GetProjectileState();
void Event_CreateProjectile( idEntity *owner, const idVec3 &start, const idVec3 &dir );
void Event_LaunchProjectile( const idVec3 &start, const idVec3 &dir, const idVec3 &pushVelocity );
void Event_SetGravity( float gravity );
virtual void Think();
virtual void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
virtual bool Collide( const trace_t &collision, const idVec3 &velocity );
virtual void Explode( const trace_t &collision, idEntity *ignore );
void Fizzle();
static idVec3 GetVelocity( const idDict *projectile );
static idVec3 GetGravity( const idDict *projectile );
enum {
EVENT_DAMAGE_EFFECT = idEntity::EVENT_MAXEVENTS,
EVENT_MAXEVENTS
};
void SetLaunchedFromGrabber( bool bl ) { launchedFromGrabber = bl; }
bool GetLaunchedFromGrabber() { return launchedFromGrabber; }
static void DefaultDamageEffect( idEntity *soundEnt, const idDict &projectileDef, const trace_t &collision, const idVec3 &velocity );
static bool ClientPredictionCollide( idEntity *soundEnt, const idDict &projectileDef, const trace_t &collision, const idVec3 &velocity, bool addDamageEffect );
virtual void ClientPredictionThink();
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void WriteToSnapshot( idBitMsg &msg ) const;
virtual void ReadFromSnapshot( const idBitMsg &msg );
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
void QueueToSimulate( int startTime );
virtual void SimulateProjectileFrame( int msec, int endTime );
virtual void PostSimulate( int endTime );
struct simulatedProjectile_t {
simulatedProjectile_t(): projectile( NULL ), startTime( 0 ) {}
idProjectile* projectile;
int startTime;
};
static const int MAX_SIMULATED_PROJECTILES = 64;
// This list is used to "catch up" client projectiles to the current time on the server
static idArray< simulatedProjectile_t, MAX_SIMULATED_PROJECTILES > projectilesToSimulate;
protected:
idEntityPtr<idEntity> owner;
struct projectileFlags_s {
bool detonate_on_world : 1;
bool detonate_on_actor : 1;
bool randomShaderSpin : 1;
bool isTracer : 1;
bool noSplashDamage : 1;
} projectileFlags;
bool launchedFromGrabber;
float thrust;
int thrust_end;
float damagePower;
renderLight_t renderLight;
qhandle_t lightDefHandle; // handle to renderer light def
idVec3 lightOffset;
int lightStartTime;
int lightEndTime;
idVec3 lightColor;
idForce_Constant thruster;
idPhysics_RigidBody physicsObj;
const idDeclParticle * smokeFly;
int smokeFlyTime;
bool mNoExplodeDisappear;
bool mTouchTriggers;
int originalTimeGroup;
typedef enum {
// must update these in script/doom_defs.script if changed
SPAWNED = 0,
CREATED = 1,
LAUNCHED = 2,
FIZZLED = 3,
EXPLODED = 4
} projectileState_t;
projectileState_t state;
private:
idVec3 launchOrigin;
idMat3 launchAxis;
void AddDefaultDamageEffect( const trace_t &collision, const idVec3 &velocity );
void AddParticlesAndLight();
void Event_Explode();
void Event_Fizzle();
void Event_RadiusDamage( idEntity *ignore );
void Event_Touch( idEntity *other, trace_t *trace );
void Event_GetProjectileState();
};
class idGuidedProjectile : public idProjectile {
public :
CLASS_PROTOTYPE( idGuidedProjectile );
idGuidedProjectile();
~idGuidedProjectile();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
virtual void Think();
virtual void Launch( const idVec3 &start, const idVec3 &dir, const idVec3 &pushVelocity, const float timeSinceFire = 0.0f, const float launchPower = 1.0f, const float dmgPower = 1.0f );
void SetEnemy( idEntity *ent );
void Event_SetEnemy(idEntity *ent);
protected:
float speed;
idEntityPtr<idEntity> enemy;
virtual void GetSeekPos( idVec3 &out );
private:
idAngles rndScale;
idAngles rndAng;
idAngles angles;
int rndUpdateTime;
float turn_max;
float clamp_dist;
bool burstMode;
bool unGuided;
float burstDist;
float burstVelocity;
};
class idSoulCubeMissile : public idGuidedProjectile {
public:
CLASS_PROTOTYPE ( idSoulCubeMissile );
~idSoulCubeMissile();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
virtual void Think();
virtual void Launch( const idVec3 &start, const idVec3 &dir, const idVec3 &pushVelocity, const float timeSinceFire = 0.0f, const float power = 1.0f, const float dmgPower = 1.0f );
protected:
virtual void GetSeekPos( idVec3 &out );
void ReturnToOwner();
void KillTarget( const idVec3 &dir );
private:
idVec3 startingVelocity;
idVec3 endingVelocity;
float accelTime;
int launchTime;
bool killPhase;
bool returnPhase;
idVec3 destOrg;
idVec3 orbitOrg;
int orbitTime;
int smokeKillTime;
const idDeclParticle * smokeKill;
};
struct beamTarget_t {
idEntityPtr<idEntity> target;
renderEntity_t renderEntity;
qhandle_t modelDefHandle;
};
class idBFGProjectile : public idProjectile {
public :
CLASS_PROTOTYPE( idBFGProjectile );
idBFGProjectile();
~idBFGProjectile();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
virtual void Think();
virtual void Launch( const idVec3 &start, const idVec3 &dir, const idVec3 &pushVelocity, const float timeSinceFire = 0.0f, const float launchPower = 1.0f, const float dmgPower = 1.0f );
virtual void Explode( const trace_t &collision, idEntity *ignore );
private:
idList<beamTarget_t, TAG_PROJECTILE> beamTargets;
renderEntity_t secondModel;
qhandle_t secondModelDefHandle;
int nextDamageTime;
idStr damageFreq;
void FreeBeams();
void Event_RemoveBeams();
void ApplyDamage();
};
class idHomingProjectile : public idProjectile {
public :
CLASS_PROTOTYPE( idHomingProjectile );
idHomingProjectile();
~idHomingProjectile();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
virtual void Think();
virtual void Launch( const idVec3 &start, const idVec3 &dir, const idVec3 &pushVelocity, const float timeSinceFire = 0.0f, const float launchPower = 1.0f, const float dmgPower = 1.0f );
void SetEnemy( idEntity *ent );
void SetSeekPos( idVec3 pos );
void Event_SetEnemy(idEntity *ent);
protected:
float speed;
idEntityPtr<idEntity> enemy;
idVec3 seekPos;
private:
idAngles rndScale;
idAngles rndAng;
idAngles angles;
float turn_max;
float clamp_dist;
bool burstMode;
bool unGuided;
float burstDist;
float burstVelocity;
};
/*
===============================================================================
idDebris
===============================================================================
*/
class idDebris : public idEntity {
public :
CLASS_PROTOTYPE( idDebris );
idDebris();
~idDebris();
// save games
void Save( idSaveGame *savefile ) const; // archives object for save game file
void Restore( idRestoreGame *savefile ); // unarchives object from save game file
void Spawn();
void Create( idEntity *owner, const idVec3 &start, const idMat3 &axis );
void Launch();
void Think();
void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
void Explode();
void Fizzle();
virtual bool Collide( const trace_t &collision, const idVec3 &velocity );
private:
idEntityPtr<idEntity> owner;
idPhysics_RigidBody physicsObj;
const idDeclParticle * smokeFly;
int smokeFlyTime;
const idSoundShader * sndBounce;
void Event_Explode();
void Event_Fizzle();
};
#endif /* !__GAME_PROJECTILE_H__ */

1421
neo/d3xp/Pvs.cpp Normal file

File diff suppressed because it is too large Load Diff

126
neo/d3xp/Pvs.h Normal file
View File

@@ -0,0 +1,126 @@
/*
===========================================================================
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 __GAME_PVS_H__
#define __GAME_PVS_H__
/*
===================================================================================
PVS
Note: mirrors and other special view portals are not taken into account
===================================================================================
*/
typedef struct pvsHandle_s {
int i; // index to current pvs
unsigned int h; // handle for current pvs
} pvsHandle_t;
typedef struct pvsCurrent_s {
pvsHandle_t handle; // current pvs handle
byte * pvs; // current pvs bit string
} pvsCurrent_t;
#define MAX_CURRENT_PVS 64 // must be a power of 2
typedef enum {
PVS_NORMAL = 0, // PVS through portals taking portal states into account
PVS_ALL_PORTALS_OPEN = 1, // PVS through portals assuming all portals are open
PVS_CONNECTED_AREAS = 2 // PVS considering all topologically connected areas visible
} pvsType_t;
class idPVS {
public:
idPVS();
~idPVS();
// setup for the current map
void Init();
void Shutdown();
// get the area(s) the source is in
int GetPVSArea( const idVec3 &point ) const; // returns the area number
int GetPVSAreas( const idBounds &bounds, int *areas, int maxAreas ) const; // returns number of areas
// setup current PVS for the source
pvsHandle_t SetupCurrentPVS( const idVec3 &source, const pvsType_t type = PVS_NORMAL ) const;
pvsHandle_t SetupCurrentPVS( const idBounds &source, const pvsType_t type = PVS_NORMAL ) const;
pvsHandle_t SetupCurrentPVS( const int sourceArea, const pvsType_t type = PVS_NORMAL ) const;
pvsHandle_t SetupCurrentPVS( const int *sourceAreas, const int numSourceAreas, const pvsType_t type = PVS_NORMAL ) const;
pvsHandle_t MergeCurrentPVS( pvsHandle_t pvs1, pvsHandle_t pvs2 ) const;
void FreeCurrentPVS( pvsHandle_t handle ) const;
// returns true if the target is within the current PVS
bool InCurrentPVS( const pvsHandle_t handle, const idVec3 &target ) const;
bool InCurrentPVS( const pvsHandle_t handle, const idBounds &target ) const;
bool InCurrentPVS( const pvsHandle_t handle, const int targetArea ) const;
bool InCurrentPVS( const pvsHandle_t handle, const int *targetAreas, int numTargetAreas ) const;
// draw all portals that are within the PVS of the source
void DrawPVS( const idVec3 &source, const pvsType_t type = PVS_NORMAL ) const;
void DrawPVS( const idBounds &source, const pvsType_t type = PVS_NORMAL ) const;
// visualize the PVS the handle points to
void DrawCurrentPVS( const pvsHandle_t handle, const idVec3 &source ) const;
bool CheckAreasForPortalSky( const pvsHandle_t handle, const idVec3 &origin );
private:
int numAreas;
int numPortals;
bool * connectedAreas;
int * areaQueue;
byte * areaPVS;
// current PVS for a specific source possibly taking portal states (open/closed) into account
mutable pvsCurrent_t currentPVS[MAX_CURRENT_PVS];
// used to create PVS
int portalVisBytes;
int portalVisLongs;
int areaVisBytes;
int areaVisLongs;
struct pvsPortal_s *pvsPortals;
struct pvsArea_s * pvsAreas;
private:
int GetPortalCount() const;
void CreatePVSData();
void DestroyPVSData();
void CopyPortalPVSToMightSee() const;
void FloodFrontPortalPVS_r( struct pvsPortal_s *portal, int areaNum ) const;
void FrontPortalPVS() const;
struct pvsStack_s * FloodPassagePVS_r( struct pvsPortal_s *source, const struct pvsPortal_s *portal, struct pvsStack_s *prevStack ) const;
void PassagePVS() const;
void AddPassageBoundaries( const idWinding &source, const idWinding &pass, bool flipClip, idPlane *bounds, int &numBounds, int maxBounds ) const;
void CreatePassages() const;
void DestroyPassages() const;
int AreaPVSFromPortalPVS() const;
void GetConnectedAreas( int srcArea, bool *connectedAreas ) const;
pvsHandle_t AllocCurrentPVS( unsigned int h ) const;
};
#endif /* !__GAME_PVS_H__ */

587
neo/d3xp/SecurityCamera.cpp Normal file
View File

@@ -0,0 +1,587 @@
/*
===========================================================================
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.
===========================================================================
*/
/*
SecurityCamera.cpp
Security camera that triggers targets when player is in view
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
/***********************************************************************
idSecurityCamera
***********************************************************************/
const idEventDef EV_SecurityCam_ReverseSweep( "<reverseSweep>" );
const idEventDef EV_SecurityCam_ContinueSweep( "<continueSweep>" );
const idEventDef EV_SecurityCam_Pause( "<pause>" );
const idEventDef EV_SecurityCam_Alert( "<alert>" );
const idEventDef EV_SecurityCam_AddLight( "<addLight>" );
CLASS_DECLARATION( idEntity, idSecurityCamera )
EVENT( EV_SecurityCam_ReverseSweep, idSecurityCamera::Event_ReverseSweep )
EVENT( EV_SecurityCam_ContinueSweep, idSecurityCamera::Event_ContinueSweep )
EVENT( EV_SecurityCam_Pause, idSecurityCamera::Event_Pause )
EVENT( EV_SecurityCam_Alert, idSecurityCamera::Event_Alert )
EVENT( EV_SecurityCam_AddLight, idSecurityCamera::Event_AddLight )
END_CLASS
/*
================
idSecurityCamera::Save
================
*/
void idSecurityCamera::Save( idSaveGame *savefile ) const {
savefile->WriteFloat( angle );
savefile->WriteFloat( sweepAngle );
savefile->WriteInt( modelAxis );
savefile->WriteBool( flipAxis );
savefile->WriteFloat( scanDist );
savefile->WriteFloat( scanFov );
savefile->WriteFloat( sweepStart );
savefile->WriteFloat( sweepEnd );
savefile->WriteBool( negativeSweep );
savefile->WriteBool( sweeping );
savefile->WriteInt( alertMode );
savefile->WriteFloat( stopSweeping );
savefile->WriteFloat( scanFovCos );
savefile->WriteVec3( viewOffset );
savefile->WriteInt( pvsArea );
savefile->WriteStaticObject( physicsObj );
savefile->WriteTraceModel( trm );
}
/*
================
idSecurityCamera::Restore
================
*/
void idSecurityCamera::Restore( idRestoreGame *savefile ) {
savefile->ReadFloat( angle );
savefile->ReadFloat( sweepAngle );
savefile->ReadInt( modelAxis );
savefile->ReadBool( flipAxis );
savefile->ReadFloat( scanDist );
savefile->ReadFloat( scanFov );
savefile->ReadFloat( sweepStart );
savefile->ReadFloat( sweepEnd );
savefile->ReadBool( negativeSweep );
savefile->ReadBool( sweeping );
savefile->ReadInt( alertMode );
savefile->ReadFloat( stopSweeping );
savefile->ReadFloat( scanFovCos );
savefile->ReadVec3( viewOffset );
savefile->ReadInt( pvsArea );
savefile->ReadStaticObject( physicsObj );
savefile->ReadTraceModel( trm );
}
/*
================
idSecurityCamera::Spawn
================
*/
void idSecurityCamera::Spawn() {
idStr str;
sweepAngle = spawnArgs.GetFloat( "sweepAngle", "90" );
health = spawnArgs.GetInt( "health", "100" );
scanFov = spawnArgs.GetFloat( "scanFov", "90" );
scanDist = spawnArgs.GetFloat( "scanDist", "200" );
flipAxis = spawnArgs.GetBool( "flipAxis" );
modelAxis = spawnArgs.GetInt( "modelAxis" );
if ( modelAxis < 0 || modelAxis > 2 ) {
modelAxis = 0;
}
spawnArgs.GetVector( "viewOffset", "0 0 0", viewOffset );
if ( spawnArgs.GetBool( "spotLight" ) ) {
PostEventMS( &EV_SecurityCam_AddLight, 0 );
}
negativeSweep = ( sweepAngle < 0 ) ? true : false;
sweepAngle = abs( sweepAngle );
scanFovCos = cos( scanFov * idMath::PI / 360.0f );
angle = GetPhysics()->GetAxis().ToAngles().yaw;
StartSweep();
SetAlertMode( SCANNING );
BecomeActive( TH_THINK );
if ( health ) {
fl.takedamage = true;
}
pvsArea = gameLocal.pvs.GetPVSArea( GetPhysics()->GetOrigin() );
// if no target specified use ourself
str = spawnArgs.GetString( "cameraTarget" );
if ( str.Length() == 0 ) {
spawnArgs.Set( "cameraTarget", spawnArgs.GetString( "name" ) );
}
// check if a clip model is set
spawnArgs.GetString( "clipmodel", "", str );
if ( !str[0] ) {
str = spawnArgs.GetString( "model" ); // use the visual model
}
if ( !collisionModelManager->TrmFromModel( str, trm ) ) {
gameLocal.Error( "idSecurityCamera '%s': cannot load collision model %s", name.c_str(), str.c_str() );
return;
}
GetPhysics()->SetContents( CONTENTS_SOLID );
GetPhysics()->SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
// setup the physics
UpdateChangeableSpawnArgs( NULL );
}
/*
================
idSecurityCamera::Event_AddLight
================
*/
void idSecurityCamera::Event_AddLight() {
idDict args;
idVec3 right, up, target, temp;
idVec3 dir;
float radius;
idVec3 lightOffset;
idLight *spotLight;
dir = GetAxis();
dir.NormalVectors( right, up );
target = GetPhysics()->GetOrigin() + dir * scanDist;
radius = tan( scanFov * idMath::PI / 360.0f );
up = dir + up * radius;
up.Normalize();
up = GetPhysics()->GetOrigin() + up * scanDist;
up -= target;
right = dir + right * radius;
right.Normalize();
right = GetPhysics()->GetOrigin() + right * scanDist;
right -= target;
spawnArgs.GetVector( "lightOffset", "0 0 0", lightOffset );
args.Set( "origin", ( GetPhysics()->GetOrigin() + lightOffset ).ToString() );
args.Set( "light_target", target.ToString() );
args.Set( "light_right", right.ToString() );
args.Set( "light_up", up.ToString() );
args.SetFloat( "angle", GetPhysics()->GetAxis()[0].ToYaw() );
spotLight = static_cast<idLight *>( gameLocal.SpawnEntityType( idLight::Type, &args ) );
spotLight->Bind( this, true );
spotLight->UpdateVisuals();
}
/*
================
idSecurityCamera::DrawFov
================
*/
void idSecurityCamera::DrawFov() {
int i;
float radius, a, s, c, halfRadius;
idVec3 right, up;
idVec4 color(1, 0, 0, 1), color2(0, 0, 1, 1);
idVec3 lastPoint, point, lastHalfPoint, halfPoint, center;
idVec3 dir = GetAxis();
dir.NormalVectors( right, up );
radius = tan( scanFov * idMath::PI / 360.0f );
halfRadius = radius * 0.5f;
lastPoint = dir + up * radius;
lastPoint.Normalize();
lastPoint = GetPhysics()->GetOrigin() + lastPoint * scanDist;
lastHalfPoint = dir + up * halfRadius;
lastHalfPoint.Normalize();
lastHalfPoint = GetPhysics()->GetOrigin() + lastHalfPoint * scanDist;
center = GetPhysics()->GetOrigin() + dir * scanDist;
for ( i = 1; i < 12; i++ ) {
a = idMath::TWO_PI * i / 12.0f;
idMath::SinCos( a, s, c );
point = dir + right * s * radius + up * c * radius;
point.Normalize();
point = GetPhysics()->GetOrigin() + point * scanDist;
gameRenderWorld->DebugLine( color, lastPoint, point );
gameRenderWorld->DebugLine( color, GetPhysics()->GetOrigin(), point );
lastPoint = point;
halfPoint = dir + right * s * halfRadius + up * c * halfRadius;
halfPoint.Normalize();
halfPoint = GetPhysics()->GetOrigin() + halfPoint * scanDist;
gameRenderWorld->DebugLine( color2, point, halfPoint );
gameRenderWorld->DebugLine( color2, lastHalfPoint, halfPoint );
lastHalfPoint = halfPoint;
gameRenderWorld->DebugLine( color2, halfPoint, center );
}
}
/*
================
idSecurityCamera::GetRenderView
================
*/
renderView_t *idSecurityCamera::GetRenderView() {
renderView_t *rv = idEntity::GetRenderView();
rv->fov_x = scanFov;
rv->fov_y = scanFov;
rv->viewaxis = GetAxis().ToAngles().ToMat3();
rv->vieworg = GetPhysics()->GetOrigin() + viewOffset;
return rv;
}
/*
================
idSecurityCamera::CanSeePlayer
================
*/
bool idSecurityCamera::CanSeePlayer() {
int i;
float dist;
idPlayer *ent;
trace_t tr;
idVec3 dir;
pvsHandle_t handle;
handle = gameLocal.pvs.SetupCurrentPVS( pvsArea );
for ( i = 0; i < gameLocal.numClients; i++ ) {
ent = static_cast<idPlayer*>(gameLocal.entities[ i ]);
if ( !ent || ( ent->fl.notarget ) ) {
continue;
}
// if there is no way we can see this player
if ( !gameLocal.pvs.InCurrentPVS( handle, ent->GetPVSAreas(), ent->GetNumPVSAreas() ) ) {
continue;
}
dir = ent->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
dist = dir.Normalize();
if ( dist > scanDist ) {
continue;
}
if ( dir * GetAxis() < scanFovCos ) {
continue;
}
idVec3 eye;
eye = ent->EyeOffset();
gameLocal.clip.TracePoint( tr, GetPhysics()->GetOrigin(), ent->GetPhysics()->GetOrigin() + eye, MASK_OPAQUE, this );
if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == ent ) ) {
gameLocal.pvs.FreeCurrentPVS( handle );
return true;
}
}
gameLocal.pvs.FreeCurrentPVS( handle );
return false;
}
/*
================
idSecurityCamera::SetAlertMode
================
*/
void idSecurityCamera::SetAlertMode( int alert ) {
if (alert >= SCANNING && alert <= ACTIVATED) {
alertMode = alert;
}
renderEntity.shaderParms[ SHADERPARM_MODE ] = alertMode;
UpdateVisuals();
}
/*
================
idSecurityCamera::Think
================
*/
void idSecurityCamera::Think() {
float pct;
float travel;
if ( thinkFlags & TH_THINK ) {
if ( g_showEntityInfo.GetBool() ) {
DrawFov();
}
if (health <= 0) {
BecomeInactive( TH_THINK );
return;
}
}
// run physics
RunPhysics();
if ( thinkFlags & TH_THINK ) {
if (CanSeePlayer()) {
if (alertMode == SCANNING) {
float sightTime;
SetAlertMode(ALERT);
stopSweeping = gameLocal.time;
if (sweeping) {
CancelEvents( &EV_SecurityCam_Pause );
} else {
CancelEvents( &EV_SecurityCam_ReverseSweep );
}
sweeping = false;
StopSound( SND_CHANNEL_ANY, false );
StartSound( "snd_sight", SND_CHANNEL_BODY, 0, false, NULL );
sightTime = spawnArgs.GetFloat( "sightTime", "5" );
PostEventSec(&EV_SecurityCam_Alert, sightTime);
}
} else {
if (alertMode == ALERT) {
float sightResume;
SetAlertMode(LOSINGINTEREST);
CancelEvents( &EV_SecurityCam_Alert );
sightResume = spawnArgs.GetFloat( "sightResume", "1.5" );
PostEventSec( &EV_SecurityCam_ContinueSweep, sightResume );
}
if ( sweeping ) {
idAngles a = GetPhysics()->GetAxis().ToAngles();
pct = ( gameLocal.time - sweepStart ) / ( sweepEnd - sweepStart );
travel = pct * sweepAngle;
if ( negativeSweep ) {
a.yaw = angle + travel;
} else {
a.yaw = angle - travel;
}
SetAngles( a );
}
}
}
Present();
}
/*
================
idSecurityCamera::GetAxis
================
*/
const idVec3 idSecurityCamera::GetAxis() const {
return (flipAxis) ? -GetPhysics()->GetAxis()[modelAxis] : GetPhysics()->GetAxis()[modelAxis];
};
/*
================
idSecurityCamera::SweepSpeed
================
*/
float idSecurityCamera::SweepSpeed() const {
return spawnArgs.GetFloat( "sweepSpeed", "5" );
}
/*
================
idSecurityCamera::StartSweep
================
*/
void idSecurityCamera::StartSweep() {
int speed;
sweeping = true;
sweepStart = gameLocal.time;
speed = SEC2MS( SweepSpeed() );
sweepEnd = sweepStart + speed;
PostEventMS( &EV_SecurityCam_Pause, speed );
StartSound( "snd_moving", SND_CHANNEL_BODY, 0, false, NULL );
}
/*
================
idSecurityCamera::Event_ContinueSweep
================
*/
void idSecurityCamera::Event_ContinueSweep() {
float pct = (stopSweeping - sweepStart) / (sweepEnd - sweepStart);
float f = gameLocal.time - (sweepEnd - sweepStart) * pct;
int speed;
sweepStart = f;
speed = MS2SEC( SweepSpeed() );
sweepEnd = sweepStart + speed;
PostEventMS( &EV_SecurityCam_Pause, speed * (1.0 - pct));
StartSound( "snd_moving", SND_CHANNEL_BODY, 0, false, NULL );
SetAlertMode(SCANNING);
sweeping = true;
}
/*
================
idSecurityCamera::Event_Alert
================
*/
void idSecurityCamera::Event_Alert() {
float wait;
SetAlertMode(ACTIVATED);
StopSound( SND_CHANNEL_ANY, false );
StartSound( "snd_activate", SND_CHANNEL_BODY, 0, false, NULL );
ActivateTargets(this);
CancelEvents( &EV_SecurityCam_ContinueSweep );
wait = spawnArgs.GetFloat( "wait", "20" );
PostEventSec( &EV_SecurityCam_ContinueSweep, wait );
}
/*
================
idSecurityCamera::Event_ReverseSweep
================
*/
void idSecurityCamera::Event_ReverseSweep() {
angle = GetPhysics()->GetAxis().ToAngles().yaw;
negativeSweep = !negativeSweep;
StartSweep();
}
/*
================
idSecurityCamera::Event_Pause
================
*/
void idSecurityCamera::Event_Pause() {
float sweepWait;
sweepWait = spawnArgs.GetFloat( "sweepWait", "0.5" );
sweeping = false;
StopSound( SND_CHANNEL_ANY, false );
StartSound( "snd_stop", SND_CHANNEL_BODY, 0, false, NULL );
PostEventSec( &EV_SecurityCam_ReverseSweep, sweepWait );
}
/*
============
idSecurityCamera::Killed
============
*/
void idSecurityCamera::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
sweeping = false;
StopSound( SND_CHANNEL_ANY, false );
const char *fx = spawnArgs.GetString( "fx_destroyed" );
if ( fx[0] != '\0' ) {
idEntityFx::StartFx( fx, NULL, NULL, this, true );
}
physicsObj.SetSelf( this );
physicsObj.SetClipModel( new (TAG_PHYSICS_CLIP_ENTITY) idClipModel( trm ), 0.02f );
physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
physicsObj.SetAxis( GetPhysics()->GetAxis() );
physicsObj.SetBouncyness( 0.2f );
physicsObj.SetFriction( 0.6f, 0.6f, 0.2f );
physicsObj.SetGravity( gameLocal.GetGravity() );
physicsObj.SetContents( CONTENTS_SOLID );
physicsObj.SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
SetPhysics( &physicsObj );
physicsObj.DropToFloor();
}
/*
============
idSecurityCamera::Pain
============
*/
bool idSecurityCamera::Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
const char *fx = spawnArgs.GetString( "fx_damage" );
if ( fx[0] != '\0' ) {
idEntityFx::StartFx( fx, NULL, NULL, this, true );
}
return true;
}
/*
================
idSecurityCamera::Present
Present is called to allow entities to generate refEntities, lights, etc for the renderer.
================
*/
void idSecurityCamera::Present() {
// don't present to the renderer if the entity hasn't changed
if ( !( thinkFlags & TH_UPDATEVISUALS ) ) {
return;
}
BecomeInactive( TH_UPDATEVISUALS );
// camera target for remote render views
if ( cameraTarget ) {
renderEntity.remoteRenderView = cameraTarget->GetRenderView();
}
// if set to invisible, skip
if ( !renderEntity.hModel || IsHidden() ) {
return;
}
// add to refresh list
if ( modelDefHandle == -1 ) {
modelDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
} else {
gameRenderWorld->UpdateEntityDef( modelDefHandle, &renderEntity );
}
}

97
neo/d3xp/SecurityCamera.h Normal file
View File

@@ -0,0 +1,97 @@
/*
===========================================================================
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 __GAME_SECURITYCAMERA_H__
#define __GAME_SECURITYCAMERA_H__
/*
===================================================================================
Security camera
===================================================================================
*/
class idSecurityCamera : public idEntity {
public:
CLASS_PROTOTYPE( idSecurityCamera );
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Think();
virtual renderView_t * GetRenderView();
virtual void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
virtual bool Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
virtual void Present();
private:
enum { SCANNING, LOSINGINTEREST, ALERT, ACTIVATED };
float angle;
float sweepAngle;
int modelAxis;
bool flipAxis;
float scanDist;
float scanFov;
float sweepStart;
float sweepEnd;
bool negativeSweep;
bool sweeping;
int alertMode;
float stopSweeping;
float scanFovCos;
idVec3 viewOffset;
int pvsArea;
idPhysics_RigidBody physicsObj;
idTraceModel trm;
void StartSweep();
bool CanSeePlayer();
void SetAlertMode( int status );
void DrawFov();
const idVec3 GetAxis() const;
float SweepSpeed() const;
void Event_ReverseSweep();
void Event_ContinueSweep();
void Event_Pause();
void Event_Alert();
void Event_AddLight();
};
#endif /* !__GAME_SECURITYCAMERA_H__ */

438
neo/d3xp/SmokeParticles.cpp Normal file
View File

@@ -0,0 +1,438 @@
/*
===========================================================================
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.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
static const char *smokeParticle_SnapshotName = "_SmokeParticle_Snapshot_";
/*
================
idSmokeParticles::idSmokeParticles
================
*/
idSmokeParticles::idSmokeParticles() {
initialized = false;
memset( &renderEntity, 0, sizeof( renderEntity ) );
renderEntityHandle = -1;
memset( smokes, 0, sizeof( smokes ) );
freeSmokes = NULL;
numActiveSmokes = 0;
currentParticleTime = -1;
}
/*
================
idSmokeParticles::Init
================
*/
void idSmokeParticles::Init() {
if ( initialized ) {
Shutdown();
}
// set up the free list
for ( int i = 0; i < MAX_SMOKE_PARTICLES-1; i++ ) {
smokes[i].next = &smokes[i+1];
}
smokes[MAX_SMOKE_PARTICLES-1].next = NULL;
freeSmokes = &smokes[0];
numActiveSmokes = 0;
activeStages.Clear();
memset( &renderEntity, 0, sizeof( renderEntity ) );
renderEntity.bounds.Clear();
renderEntity.axis = mat3_identity;
renderEntity.shaderParms[ SHADERPARM_RED ] = 1;
renderEntity.shaderParms[ SHADERPARM_GREEN ] = 1;
renderEntity.shaderParms[ SHADERPARM_BLUE ] = 1;
renderEntity.shaderParms[3] = 1;
renderEntity.hModel = renderModelManager->AllocModel();
renderEntity.hModel->InitEmpty( smokeParticle_SnapshotName );
// we certainly don't want particle shadows
renderEntity.noShadow = 1;
// huge bounds, so it will be present in every world area
renderEntity.bounds.AddPoint( idVec3(-100000, -100000, -100000) );
renderEntity.bounds.AddPoint( idVec3( 100000, 100000, 100000) );
renderEntity.callback = idSmokeParticles::ModelCallback;
// add to renderer list
renderEntityHandle = gameRenderWorld->AddEntityDef( &renderEntity );
currentParticleTime = -1;
initialized = true;
}
/*
================
idSmokeParticles::Shutdown
================
*/
void idSmokeParticles::Shutdown() {
// make sure the render entity is freed before the model is freed
if ( renderEntityHandle != -1 ) {
gameRenderWorld->FreeEntityDef( renderEntityHandle );
renderEntityHandle = -1;
}
if ( renderEntity.hModel != NULL ) {
renderModelManager->FreeModel( renderEntity.hModel );
renderEntity.hModel = NULL;
}
initialized = false;
}
/*
================
idSmokeParticles::FreeSmokes
================
*/
void idSmokeParticles::FreeSmokes() {
for ( int activeStageNum = 0; activeStageNum < activeStages.Num(); activeStageNum++ ) {
singleSmoke_t *smoke, *next, *last;
activeSmokeStage_t *active = &activeStages[activeStageNum];
const idParticleStage *stage = active->stage;
for ( last = NULL, smoke = active->smokes; smoke; smoke = next ) {
next = smoke->next;
float frac;
if ( smoke->timeGroup ) {
frac = (float)( gameLocal.fast.time - smoke->privateStartTime ) / ( stage->particleLife * 1000 );
}
else {
frac = (float)( gameLocal.slow.time - smoke->privateStartTime ) / ( stage->particleLife * 1000 );
}
if ( frac >= 1.0f ) {
// remove the particle from the stage list
if ( last != NULL ) {
last->next = smoke->next;
} else {
active->smokes = smoke->next;
}
// put the particle on the free list
smoke->next = freeSmokes;
freeSmokes = smoke;
numActiveSmokes--;
continue;
}
last = smoke;
}
if ( !active->smokes ) {
// remove this from the activeStages list
activeStages.RemoveIndex( activeStageNum );
activeStageNum--;
}
}
}
/*
================
idSmokeParticles::EmitSmoke
Called by game code to drop another particle into the list
================
*/
bool idSmokeParticles::EmitSmoke( const idDeclParticle *smoke, const int systemStartTime, const float diversity, const idVec3 &origin, const idMat3 &axis, int timeGroup /*_D3XP*/ ) {
bool continues = false;
SetTimeState ts( timeGroup );
if ( !smoke ) {
return false;
}
if ( !gameLocal.isNewFrame ) {
return false;
}
// dedicated doesn't smoke. No UpdateRenderEntity, so they would not be freed
if ( gameLocal.GetLocalClientNum() < 0 ) {
return false;
}
assert( gameLocal.time == 0 || systemStartTime <= gameLocal.time );
if ( systemStartTime > gameLocal.time ) {
return false;
}
idRandom steppingRandom( 0xffff * diversity );
// for each stage in the smoke that is still emitting particles, emit a new singleSmoke_t
for ( int stageNum = 0; stageNum < smoke->stages.Num(); stageNum++ ) {
const idParticleStage *stage = smoke->stages[stageNum];
if ( !stage->cycleMsec ) {
continue;
}
if ( !stage->material ) {
continue;
}
if ( stage->particleLife <= 0 ) {
continue;
}
// see how many particles we should emit this tic
// FIXME: smoke.privateStartTime += stage->timeOffset;
int finalParticleTime = stage->cycleMsec * stage->spawnBunching;
int deltaMsec = gameLocal.time - systemStartTime;
int nowCount = 0, prevCount = 0;
if ( finalParticleTime == 0 ) {
// if spawnBunching is 0, they will all come out at once
if ( gameLocal.time == systemStartTime ) {
prevCount = -1;
nowCount = stage->totalParticles-1;
} else {
prevCount = stage->totalParticles;
}
} else {
nowCount = floor( ( (float)deltaMsec / finalParticleTime ) * stage->totalParticles );
if ( nowCount >= stage->totalParticles ) {
nowCount = stage->totalParticles-1;
}
prevCount = floor( ((float)( deltaMsec - ( gameLocal.time - gameLocal.previousTime ) ) / finalParticleTime) * stage->totalParticles );
if ( prevCount < -1 ) {
prevCount = -1;
}
}
if ( prevCount >= stage->totalParticles ) {
// no more particles from this stage
continue;
}
if ( nowCount < stage->totalParticles-1 ) {
// the system will need to emit particles next frame as well
continues = true;
}
// find an activeSmokeStage that matches this
activeSmokeStage_t *active = NULL;
int i;
for ( i = 0 ; i < activeStages.Num() ; i++ ) {
active = &activeStages[i];
if ( active->stage == stage ) {
break;
}
}
if ( i == activeStages.Num() ) {
// add a new one
activeSmokeStage_t newActive;
newActive.smokes = NULL;
newActive.stage = stage;
i = activeStages.Append( newActive );
active = &activeStages[i];
}
// add all the required particles
for ( prevCount++ ; prevCount <= nowCount && active != NULL ; prevCount++ ) {
if ( !freeSmokes ) {
gameLocal.Printf( "idSmokeParticles::EmitSmoke: no free smokes with %d active stages\n", activeStages.Num() );
return true;
}
singleSmoke_t *newSmoke = freeSmokes;
freeSmokes = freeSmokes->next;
numActiveSmokes++;
newSmoke->timeGroup = timeGroup;
newSmoke->index = prevCount;
newSmoke->axis = axis;
newSmoke->origin = origin;
newSmoke->random = steppingRandom;
newSmoke->privateStartTime = systemStartTime + prevCount * finalParticleTime / stage->totalParticles;
newSmoke->next = active->smokes;
active->smokes = newSmoke;
steppingRandom.RandomInt(); // advance the random
}
}
return continues;
}
/*
================
idSmokeParticles::UpdateRenderEntity
================
*/
bool idSmokeParticles::UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView ) {
// this may be triggered by a model trace or other non-view related source,
// to which we should look like an empty model
if ( !renderView ) {
// FIXME: re-use model surfaces
renderEntity->hModel->InitEmpty( smokeParticle_SnapshotName );
return false;
}
// don't regenerate it if it is current
if ( renderView->time[renderEntity->timeGroup] == currentParticleTime && !renderView->forceUpdate ) {
return false;
}
// FIXME: re-use model surfaces
renderEntity->hModel->InitEmpty( smokeParticle_SnapshotName );
currentParticleTime = renderView->time[renderEntity->timeGroup];
particleGen_t g;
g.renderEnt = renderEntity;
g.renderView = renderView;
for ( int activeStageNum = 0; activeStageNum < activeStages.Num(); activeStageNum++ ) {
singleSmoke_t *smoke, *next, *last;
activeSmokeStage_t *active = &activeStages[activeStageNum];
const idParticleStage *stage = active->stage;
if ( !stage->material ) {
continue;
}
// allocate a srfTriangles that can hold all the particles
int count = 0;
for ( smoke = active->smokes; smoke; smoke = smoke->next ) {
count++;
}
int quads = count * stage->NumQuadsPerParticle();
srfTriangles_t *tri = renderEntity->hModel->AllocSurfaceTriangles( quads * 4, quads * 6 );
tri->numIndexes = quads * 6;
tri->numVerts = quads * 4;
// just always draw the particles
tri->bounds[0][0] =
tri->bounds[0][1] =
tri->bounds[0][2] = -99999;
tri->bounds[1][0] =
tri->bounds[1][1] =
tri->bounds[1][2] = 99999;
tri->numVerts = 0;
for ( last = NULL, smoke = active->smokes; smoke; smoke = next ) {
next = smoke->next;
if ( smoke->timeGroup ) {
g.frac = (float)( gameLocal.fast.time - smoke->privateStartTime ) / (stage->particleLife * 1000);
}
else {
g.frac = (float)( gameLocal.time - smoke->privateStartTime ) / (stage->particleLife * 1000);
}
if ( g.frac >= 1.0f ) {
// remove the particle from the stage list
if ( last != NULL ) {
last->next = smoke->next;
} else {
active->smokes = smoke->next;
}
// put the particle on the free list
smoke->next = freeSmokes;
freeSmokes = smoke;
numActiveSmokes--;
continue;
}
g.index = smoke->index;
g.random = smoke->random;
g.origin = smoke->origin;
g.axis = smoke->axis;
g.originalRandom = g.random;
g.age = g.frac * stage->particleLife;
tri->numVerts += stage->CreateParticle( &g, tri->verts + tri->numVerts );
last = smoke;
}
if ( tri->numVerts > quads * 4 ) {
gameLocal.Error( "idSmokeParticles::UpdateRenderEntity: miscounted verts" );
}
if ( tri->numVerts == 0 ) {
// they were all removed
renderEntity->hModel->FreeSurfaceTriangles( tri );
if ( !active->smokes ) {
// remove this from the activeStages list
activeStages.RemoveIndex( activeStageNum );
activeStageNum--;
}
} else {
// build the index list
int indexes = 0;
for ( int i = 0 ; i < tri->numVerts ; i += 4 ) {
tri->indexes[indexes+0] = i;
tri->indexes[indexes+1] = i+2;
tri->indexes[indexes+2] = i+3;
tri->indexes[indexes+3] = i;
tri->indexes[indexes+4] = i+3;
tri->indexes[indexes+5] = i+1;
indexes += 6;
}
tri->numIndexes = indexes;
modelSurface_t surf;
surf.geometry = tri;
surf.shader = stage->material;
surf.id = 0;
renderEntity->hModel->AddSurface( surf );
}
}
return true;
}
/*
================
idSmokeParticles::ModelCallback
================
*/
bool idSmokeParticles::ModelCallback( renderEntity_s *renderEntity, const renderView_t *renderView ) {
// update the particles
if ( gameLocal.smokeParticles ) {
return gameLocal.smokeParticles->UpdateRenderEntity( renderEntity, renderView );
}
return true;
}

103
neo/d3xp/SmokeParticles.h Normal file
View File

@@ -0,0 +1,103 @@
/*
===========================================================================
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 __SMOKEPARTICLES_H__
#define __SMOKEPARTICLES_H__
/*
===============================================================================
Smoke systems are for particles that are emitted off of things that are
constantly changing position and orientation, like muzzle smoke coming
from a bone on a weapon, blood spurting from a wound, or particles
trailing from a monster limb.
The smoke particles are always evaluated and rendered each tic, so there
is a performance cost with using them for continuous effects. The general
particle systems are completely parametric, and have no performance
overhead when not in view.
All smoke systems share the same shaderparms, so any coloration must be
done in the particle definition.
Each particle model has its own shaderparms, which can be used by the
particle materials.
===============================================================================
*/
typedef struct singleSmoke_s {
struct singleSmoke_s * next;
int privateStartTime; // start time for this particular particle
int index; // particle index in system, 0 <= index < stage->totalParticles
idRandom random;
idVec3 origin;
idMat3 axis;
int timeGroup;
} singleSmoke_t;
typedef struct {
const idParticleStage * stage;
singleSmoke_t * smokes;
} activeSmokeStage_t;
class idSmokeParticles {
public:
idSmokeParticles();
// creats an entity covering the entire world that will call back each rendering
void Init();
void Shutdown();
// spits out a particle, returning false if the system will not emit any more particles in the future
bool EmitSmoke( const idDeclParticle *smoke, const int startTime, const float diversity,
const idVec3 &origin, const idMat3 &axis, int timeGroup /*_D3XP*/ );
// free old smokes
void FreeSmokes();
private:
bool initialized;
renderEntity_t renderEntity; // used to present a model to the renderer
int renderEntityHandle; // handle to static renderer model
static const int MAX_SMOKE_PARTICLES = 10000;
singleSmoke_t smokes[MAX_SMOKE_PARTICLES];
idList<activeSmokeStage_t, TAG_PARTICLE> activeStages;
singleSmoke_t * freeSmokes;
int numActiveSmokes;
int currentParticleTime; // don't need to recalculate if == view time
bool UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView );
static bool ModelCallback( renderEntity_s *renderEntity, const renderView_t *renderView );
};
#endif /* !__SMOKEPARTICLES_H__ */

304
neo/d3xp/Sound.cpp Normal file
View File

@@ -0,0 +1,304 @@
/*
===========================================================================
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.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
/*
===============================================================================
SOUND
===============================================================================
*/
const idEventDef EV_Speaker_On( "On", NULL );
const idEventDef EV_Speaker_Off( "Off", NULL );
const idEventDef EV_Speaker_Timer( "<timer>", NULL );
CLASS_DECLARATION( idEntity, idSound )
EVENT( EV_Activate, idSound::Event_Trigger )
EVENT( EV_Speaker_On, idSound::Event_On )
EVENT( EV_Speaker_Off, idSound::Event_Off )
EVENT( EV_Speaker_Timer, idSound::Event_Timer )
END_CLASS
/*
================
idSound::idSound
================
*/
idSound::idSound() {
lastSoundVol = 0.0f;
soundVol = 0.0f;
shakeTranslate.Zero();
shakeRotate.Zero();
random = 0.0f;
wait = 0.0f;
timerOn = false;
playingUntilTime = 0;
}
/*
================
idSound::Save
================
*/
void idSound::Save( idSaveGame *savefile ) const {
savefile->WriteFloat( lastSoundVol );
savefile->WriteFloat( soundVol );
savefile->WriteFloat( random );
savefile->WriteFloat( wait );
savefile->WriteBool( timerOn );
savefile->WriteVec3( shakeTranslate );
savefile->WriteAngles( shakeRotate );
savefile->WriteInt( playingUntilTime );
}
/*
================
idSound::Restore
================
*/
void idSound::Restore( idRestoreGame *savefile ) {
savefile->ReadFloat( lastSoundVol );
savefile->ReadFloat( soundVol );
savefile->ReadFloat( random );
savefile->ReadFloat( wait );
savefile->ReadBool( timerOn );
savefile->ReadVec3( shakeTranslate );
savefile->ReadAngles( shakeRotate );
savefile->ReadInt( playingUntilTime );
}
/*
================
idSound::Spawn
================
*/
void idSound::Spawn() {
spawnArgs.GetVector( "move", "0 0 0", shakeTranslate );
spawnArgs.GetAngles( "rotate", "0 0 0", shakeRotate );
spawnArgs.GetFloat( "random", "0", random );
spawnArgs.GetFloat( "wait", "0", wait );
if ( ( wait > 0.0f ) && ( random >= wait ) ) {
random = wait - 0.001;
gameLocal.Warning( "speaker '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
}
soundVol = 0.0f;
lastSoundVol = 0.0f;
if ( ( shakeRotate != ang_zero ) || ( shakeTranslate != vec3_zero ) ) {
BecomeActive( TH_THINK );
}
if ( !refSound.waitfortrigger && ( wait > 0.0f ) ) {
timerOn = true;
PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
} else {
timerOn = false;
}
}
/*
================
idSound::Event_Trigger
this will toggle the idle idSound on and off
================
*/
void idSound::Event_Trigger( idEntity *activator ) {
if ( wait > 0.0f ) {
if ( timerOn ) {
timerOn = false;
CancelEvents( &EV_Speaker_Timer );
} else {
timerOn = true;
DoSound( true );
PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
}
} else {
if ( common->IsMultiplayer() ) {
if ( refSound.referenceSound && ( gameLocal.time < playingUntilTime ) ) {
DoSound( false );
} else {
DoSound( true );
}
} else {
if ( refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) {
DoSound( false );
} else {
DoSound( true );
}
}
}
}
/*
================
idSound::Event_Timer
================
*/
void idSound::Event_Timer() {
DoSound( true );
PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
}
/*
================
idSound::Think
================
*/
void idSound::Think() {
idAngles ang;
// run physics
RunPhysics();
// clear out our update visuals think flag since we never call Present
BecomeInactive( TH_UPDATEVISUALS );
}
/*
===============
idSound::UpdateChangableSpawnArgs
===============
*/
void idSound::UpdateChangeableSpawnArgs( const idDict *source ) {
idEntity::UpdateChangeableSpawnArgs( source );
if ( source ) {
FreeSoundEmitter( true );
spawnArgs.Copy( *source );
idSoundEmitter *saveRef = refSound.referenceSound;
gameEdit->ParseSpawnArgsToRefSound( &spawnArgs, &refSound );
refSound.referenceSound = saveRef;
idVec3 origin;
idMat3 axis;
if ( GetPhysicsToSoundTransform( origin, axis ) ) {
refSound.origin = GetPhysics()->GetOrigin() + origin * axis;
} else {
refSound.origin = GetPhysics()->GetOrigin();
}
spawnArgs.GetFloat( "random", "0", random );
spawnArgs.GetFloat( "wait", "0", wait );
if ( ( wait > 0.0f ) && ( random >= wait ) ) {
random = wait - 0.001;
gameLocal.Warning( "speaker '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
}
if ( !refSound.waitfortrigger && ( wait > 0.0f ) ) {
timerOn = true;
DoSound( false );
CancelEvents( &EV_Speaker_Timer );
PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
} else if ( !refSound.waitfortrigger && !(refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) ) {
// start it if it isn't already playing, and we aren't waitForTrigger
DoSound( true );
timerOn = false;
}
}
}
/*
===============
idSound::SetSound
===============
*/
void idSound::SetSound( const char *sound, int channel ) {
const idSoundShader *shader = declManager->FindSound( sound );
if ( shader != refSound.shader ) {
FreeSoundEmitter( true );
}
gameEdit->ParseSpawnArgsToRefSound(&spawnArgs, &refSound);
refSound.shader = shader;
// start it if it isn't already playing, and we aren't waitForTrigger
if ( !refSound.waitfortrigger && !(refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) ) {
DoSound( true );
}
}
/*
================
idSound::DoSound
================
*/
void idSound::DoSound( bool play ) {
if ( play ) {
StartSoundShader( refSound.shader, SND_CHANNEL_ANY, refSound.parms.soundShaderFlags, true, &playingUntilTime );
playingUntilTime += gameLocal.time;
} else {
StopSound( SND_CHANNEL_ANY, true );
playingUntilTime = 0;
}
}
/*
================
idSound::Event_On
================
*/
void idSound::Event_On() {
if ( wait > 0.0f ) {
timerOn = true;
PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
}
DoSound( true );
}
/*
================
idSound::Event_Off
================
*/
void idSound::Event_Off() {
if ( timerOn ) {
timerOn = false;
CancelEvents( &EV_Speaker_Timer );
}
DoSound( false );
}
/*
===============
idSound::ShowEditingDialog
===============
*/
void idSound::ShowEditingDialog() {
}

76
neo/d3xp/Sound.h Normal file
View File

@@ -0,0 +1,76 @@
/*
===========================================================================
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 __GAME_SOUND_H__
#define __GAME_SOUND_H__
/*
===============================================================================
Generic sound emitter.
===============================================================================
*/
class idSound : public idEntity {
public:
CLASS_PROTOTYPE( idSound );
idSound();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void UpdateChangeableSpawnArgs( const idDict *source );
void Spawn();
void ToggleOnOff( idEntity *other, idEntity *activator );
void Think();
void SetSound( const char *sound, int channel = SND_CHANNEL_ANY );
virtual void ShowEditingDialog();
private:
float lastSoundVol;
float soundVol;
float random;
float wait;
bool timerOn;
idVec3 shakeTranslate;
idAngles shakeRotate;
int playingUntilTime;
void Event_Trigger( idEntity *activator );
void Event_Timer();
void Event_On();
void Event_Off();
void DoSound( bool play );
};
#endif /* !__GAME_SOUND_H__ */

1921
neo/d3xp/Target.cpp Normal file

File diff suppressed because it is too large Load Diff

615
neo/d3xp/Target.h Normal file
View File

@@ -0,0 +1,615 @@
/*
===========================================================================
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 __GAME_TARGET_H__
#define __GAME_TARGET_H__
/*
===============================================================================
idTarget
===============================================================================
*/
class idTarget : public idEntity {
public:
CLASS_PROTOTYPE( idTarget );
};
/*
===============================================================================
idTarget_Remove
===============================================================================
*/
class idTarget_Remove : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_Remove );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_Show
===============================================================================
*/
class idTarget_Show : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_Show );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_Damage
===============================================================================
*/
class idTarget_Damage : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_Damage );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_SessionCommand
===============================================================================
*/
class idTarget_SessionCommand : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_SessionCommand );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_EndLevel
===============================================================================
*/
class idTarget_EndLevel : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_EndLevel );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_WaitForButton
===============================================================================
*/
class idTarget_WaitForButton : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_WaitForButton );
void Think();
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_SetGlobalShaderTime
===============================================================================
*/
class idTarget_SetGlobalShaderTime : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_SetGlobalShaderTime );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_SetShaderParm
===============================================================================
*/
class idTarget_SetShaderParm : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_SetShaderParm );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_SetShaderTime
===============================================================================
*/
class idTarget_SetShaderTime : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_SetShaderTime );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_FadeEntity
===============================================================================
*/
class idTarget_FadeEntity : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_FadeEntity );
idTarget_FadeEntity();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Think();
private:
idVec4 fadeFrom;
int fadeStart;
int fadeEnd;
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_LightFadeIn
===============================================================================
*/
class idTarget_LightFadeIn : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_LightFadeIn );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_LightFadeOut
===============================================================================
*/
class idTarget_LightFadeOut : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_LightFadeOut );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_Give
===============================================================================
*/
class idTarget_Give : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_Give );
void Spawn();
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_GiveEmail
===============================================================================
*/
class idTarget_GiveEmail : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_GiveEmail );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_SetModel
===============================================================================
*/
class idTarget_SetModel : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_SetModel );
void Spawn();
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_SetInfluence
===============================================================================
*/
typedef struct SavedGui_s {
SavedGui_s() {memset(gui, 0, sizeof(idUserInterface*)*MAX_RENDERENTITY_GUI); };
idUserInterface* gui[MAX_RENDERENTITY_GUI];
} SavedGui_t;
class idTarget_SetInfluence : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_SetInfluence );
idTarget_SetInfluence();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
private:
void Event_Activate( idEntity *activator );
void Event_RestoreInfluence();
void Event_GatherEntities();
void Event_Flash( float flash, int out );
void Event_ClearFlash( float flash );
void Think();
idList<int, TAG_TARGET> lightList;
idList<int, TAG_TARGET> guiList;
idList<int, TAG_TARGET> soundList;
idList<int, TAG_TARGET> genericList;
float flashIn;
float flashOut;
float delay;
idStr flashInSound;
idStr flashOutSound;
idEntity * switchToCamera;
idInterpolate<float>fovSetting;
bool soundFaded;
bool restoreOnTrigger;
idList<SavedGui_t, TAG_TARGET> savedGuiList;
};
/*
===============================================================================
idTarget_SetKeyVal
===============================================================================
*/
class idTarget_SetKeyVal : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_SetKeyVal );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_SetFov
===============================================================================
*/
class idTarget_SetFov : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_SetFov );
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Think();
private:
idInterpolate<float> fovSetting;
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_SetPrimaryObjective
===============================================================================
*/
class idTarget_SetPrimaryObjective : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_SetPrimaryObjective );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_LockDoor
===============================================================================
*/
class idTarget_LockDoor: public idTarget {
public:
CLASS_PROTOTYPE( idTarget_LockDoor );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_CallObjectFunction
===============================================================================
*/
class idTarget_CallObjectFunction : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_CallObjectFunction );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_LockDoor
===============================================================================
*/
class idTarget_EnableLevelWeapons : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_EnableLevelWeapons );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_Tip
===============================================================================
*/
class idTarget_Tip : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_Tip );
idTarget_Tip();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
private:
idVec3 playerPos;
void Event_Activate( idEntity *activator );
void Event_TipOff();
void Event_GetPlayerPos();
};
/*
===============================================================================
idTarget_GiveSecurity
===============================================================================
*/
class idTarget_GiveSecurity : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_GiveSecurity );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_RemoveWeapons
===============================================================================
*/
class idTarget_RemoveWeapons : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_RemoveWeapons );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_LevelTrigger
===============================================================================
*/
class idTarget_LevelTrigger : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_LevelTrigger );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_Checkpoint
===============================================================================
*/
class idTarget_Checkpoint : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_Checkpoint );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_EnableStamina
===============================================================================
*/
class idTarget_EnableStamina : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_EnableStamina );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_FadeSoundClass
===============================================================================
*/
class idTarget_FadeSoundClass : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_FadeSoundClass );
private:
void Event_Activate( idEntity *activator );
void Event_RestoreVolume();
};
/*
===============================================================================
idTarget_RumbleJoystick
===============================================================================
*/
class idTarget_RumbleJoystick : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_RumbleJoystick );
private:
void Event_Activate( idEntity *activator );
};
/*
===============================================================================
idTarget_Achievement
===============================================================================
*/
class idTarget_Achievement : public idTarget {
public:
CLASS_PROTOTYPE( idTarget_Achievement );
private:
void Event_Activate( idEntity *activator );
};
#endif /* !__GAME_TARGET_H__ */

1357
neo/d3xp/Trigger.cpp Normal file

File diff suppressed because it is too large Load Diff

312
neo/d3xp/Trigger.h Normal file
View File

@@ -0,0 +1,312 @@
/*
===========================================================================
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 __GAME_TRIGGER_H__
#define __GAME_TRIGGER_H__
extern const idEventDef EV_Enable;
extern const idEventDef EV_Disable;
/*
===============================================================================
Trigger base.
===============================================================================
*/
class idTrigger : public idEntity {
public:
CLASS_PROTOTYPE( idTrigger );
static void DrawDebugInfo();
idTrigger();
void Spawn();
const function_t * GetScriptFunction() const;
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Enable();
virtual void Disable();
protected:
void CallScript() const;
void Event_Enable();
void Event_Disable();
const function_t * scriptFunction;
};
/*
===============================================================================
Trigger which can be activated multiple times.
===============================================================================
*/
class idTrigger_Multi : public idTrigger {
public:
CLASS_PROTOTYPE( idTrigger_Multi );
idTrigger_Multi();
void Spawn();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
protected:
float wait;
float random;
float delay;
float random_delay;
int nextTriggerTime;
idStr requires;
int removeItem;
bool touchClient;
bool touchOther;
bool triggerFirst;
bool triggerWithSelf;
bool CheckFacing( idEntity *activator );
void TriggerAction( idEntity *activator );
void Event_TriggerAction( idEntity *activator );
void Event_Trigger( idEntity *activator );
void Event_Touch( idEntity *other, trace_t *trace );
};
/*
===============================================================================
Trigger which can only be activated by an entity with a specific name.
===============================================================================
*/
class idTrigger_EntityName : public idTrigger {
public:
CLASS_PROTOTYPE( idTrigger_EntityName );
idTrigger_EntityName();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
private:
float wait;
float random;
float delay;
float random_delay;
int nextTriggerTime;
bool triggerFirst;
idStr entityName;
bool testPartialName;
void TriggerAction( idEntity *activator );
void Event_TriggerAction( idEntity *activator );
void Event_Trigger( idEntity *activator );
void Event_Touch( idEntity *other, trace_t *trace );
};
/*
===============================================================================
Trigger which repeatedly fires targets.
===============================================================================
*/
class idTrigger_Timer : public idTrigger {
public:
CLASS_PROTOTYPE( idTrigger_Timer );
idTrigger_Timer();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
virtual void Enable();
virtual void Disable();
private:
float random;
float wait;
bool on;
float delay;
idStr onName;
idStr offName;
void Event_Timer();
void Event_Use( idEntity *activator );
};
/*
===============================================================================
Trigger which fires targets after being activated a specific number of times.
===============================================================================
*/
class idTrigger_Count : public idTrigger {
public:
CLASS_PROTOTYPE( idTrigger_Count );
idTrigger_Count();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
private:
int goal;
int count;
float delay;
void Event_Trigger( idEntity *activator );
void Event_TriggerAction( idEntity *activator );
};
/*
===============================================================================
Trigger which hurts touching entities.
===============================================================================
*/
class idTrigger_Hurt : public idTrigger {
public:
CLASS_PROTOTYPE( idTrigger_Hurt );
idTrigger_Hurt();
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
void Spawn();
private:
bool on;
float delay;
int nextTime;
void Event_Touch( idEntity *other, trace_t *trace );
void Event_Toggle( idEntity *activator );
};
/*
===============================================================================
Trigger which fades the player view.
===============================================================================
*/
class idTrigger_Fade : public idTrigger {
public:
CLASS_PROTOTYPE( idTrigger_Fade );
private:
void Event_Trigger( idEntity *activator );
};
/*
===============================================================================
Trigger which continuously tests whether other entities are touching it.
===============================================================================
*/
class idTrigger_Touch : public idTrigger {
public:
CLASS_PROTOTYPE( idTrigger_Touch );
idTrigger_Touch();
void Spawn();
virtual void Think();
void Save( idSaveGame *savefile );
void Restore( idRestoreGame *savefile );
virtual void Enable();
virtual void Disable();
void TouchEntities();
private:
idClipModel * clipModel;
void Event_Trigger( idEntity *activator );
};
/*
===============================================================================
Trigger that responces to CTF flags
===============================================================================
*/
class idTrigger_Flag : public idTrigger_Multi {
public:
CLASS_PROTOTYPE( idTrigger_Flag );
idTrigger_Flag();
void Spawn();
private:
int team;
bool player; // flag must be attached/carried by player
const idEventDef * eventFlag;
void Event_Touch( idEntity *other, trace_t *trace );
};
#endif /* !__GAME_TRIGGER_H__ */

Some files were not shown because too many files have changed in this diff Show More