mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2026-03-24 02:48:08 +01:00
Initial commit
This commit is contained in:
21
neo/_Common.props
Normal file
21
neo/_Common.props
Normal 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
23
neo/_Debug.props
Normal 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
12
neo/_Dedicated.props
Normal 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
18
neo/_DoomExe.props
Normal 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
21
neo/_Game-d3xp.props
Normal 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
22
neo/_Game.props
Normal 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
25
neo/_PCLibs.props
Normal 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
27
neo/_Release.props
Normal 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
13
neo/_WithInlines.props
Normal 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
12
neo/_WithMemoryLog.props
Normal 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
14
neo/_external.props
Normal 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
13
neo/_idlib.props
Normal 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
1317
neo/aas/AASFile.cpp
Normal file
File diff suppressed because it is too large
Load Diff
351
neo/aas/AASFile.h
Normal file
351
neo/aas/AASFile.h
Normal 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__ */
|
||||
77
neo/aas/AASFileManager.cpp
Normal file
77
neo/aas/AASFileManager.cpp
Normal 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
50
neo/aas/AASFileManager.h
Normal 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
99
neo/aas/AASFile_local.h
Normal 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__ */
|
||||
155
neo/aas/AASFile_optimize.cpp
Normal file
155
neo/aas/AASFile_optimize.cpp
Normal 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
609
neo/aas/AASFile_sample.cpp
Normal 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
343
neo/amplitude/amplitude.cpp
Normal 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;
|
||||
}
|
||||
126
neo/amplitude/amplitude.vcxproj
Normal file
126
neo/amplitude/amplitude.vcxproj
Normal 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>
|
||||
6
neo/amplitude/amplitude.vcxproj.filters
Normal file
6
neo/amplitude/amplitude.vcxproj.filters
Normal 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>
|
||||
10
neo/amplitude/amplitude.vcxproj.vspscc
Normal file
10
neo/amplitude/amplitude.vcxproj.vspscc
Normal 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
150
neo/cm/CollisionModel.h
Normal 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__ */
|
||||
76
neo/cm/CollisionModel_contacts.cpp
Normal file
76
neo/cm/CollisionModel_contacts.cpp
Normal 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;
|
||||
}
|
||||
636
neo/cm/CollisionModel_contents.cpp
Normal file
636
neo/cm/CollisionModel_contents.cpp
Normal 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 );
|
||||
}
|
||||
489
neo/cm/CollisionModel_debug.cpp
Normal file
489
neo/cm/CollisionModel_debug.cpp
Normal 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;
|
||||
}
|
||||
671
neo/cm/CollisionModel_files.cpp
Normal file
671
neo/cm/CollisionModel_files.cpp
Normal 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;
|
||||
}
|
||||
4068
neo/cm/CollisionModel_load.cpp
Normal file
4068
neo/cm/CollisionModel_load.cpp
Normal file
File diff suppressed because it is too large
Load Diff
539
neo/cm/CollisionModel_local.h
Normal file
539
neo/cm/CollisionModel_local.h
Normal 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;
|
||||
1695
neo/cm/CollisionModel_rotate.cpp
Normal file
1695
neo/cm/CollisionModel_rotate.cpp
Normal file
File diff suppressed because it is too large
Load Diff
257
neo/cm/CollisionModel_trace.cpp
Normal file
257
neo/cm/CollisionModel_trace.cpp
Normal 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 );
|
||||
}
|
||||
}
|
||||
1086
neo/cm/CollisionModel_translate.cpp
Normal file
1086
neo/cm/CollisionModel_translate.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1272
neo/d3xp/AF.cpp
Normal file
1272
neo/d3xp/AF.cpp
Normal file
File diff suppressed because it is too large
Load Diff
120
neo/d3xp/AF.h
Normal file
120
neo/d3xp/AF.h
Normal 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
3676
neo/d3xp/AFEntity.cpp
Normal file
File diff suppressed because it is too large
Load Diff
597
neo/d3xp/AFEntity.h
Normal file
597
neo/d3xp/AFEntity.h
Normal 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
537
neo/d3xp/Achievements.cpp
Normal 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
184
neo/d3xp/Achievements.h
Normal 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
3474
neo/d3xp/Actor.cpp
Normal file
File diff suppressed because it is too large
Load Diff
333
neo/d3xp/Actor.h
Normal file
333
neo/d3xp/Actor.h
Normal 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
436
neo/d3xp/AimAssist.cpp
Normal 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
75
neo/d3xp/AimAssist.h
Normal 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
1386
neo/d3xp/BrittleFracture.cpp
Normal file
File diff suppressed because it is too large
Load Diff
141
neo/d3xp/BrittleFracture.h
Normal file
141
neo/d3xp/BrittleFracture.h
Normal 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
636
neo/d3xp/Camera.cpp
Normal 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
132
neo/d3xp/Camera.h
Normal 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
185
neo/d3xp/EndLevel.cpp
Normal 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
66
neo/d3xp/EndLevel.h
Normal 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
5858
neo/d3xp/Entity.cpp
Normal file
File diff suppressed because it is too large
Load Diff
711
neo/d3xp/Entity.h
Normal file
711
neo/d3xp/Entity.h
Normal 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
833
neo/d3xp/Fx.cpp
Normal 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
107
neo/d3xp/Fx.h
Normal 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
2
neo/d3xp/Game.def
Normal file
@@ -0,0 +1,2 @@
|
||||
EXPORTS
|
||||
GetGameAPI
|
||||
343
neo/d3xp/Game.h
Normal file
343
neo/d3xp/Game.h
Normal 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
1142
neo/d3xp/GameEdit.cpp
Normal file
File diff suppressed because it is too large
Load Diff
119
neo/d3xp/GameEdit.h
Normal file
119
neo/d3xp/GameEdit.h
Normal 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
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
819
neo/d3xp/Game_local.h
Normal 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
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
739
neo/d3xp/Grabber.cpp
Normal 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
84
neo/d3xp/Grabber.h
Normal 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
1128
neo/d3xp/IK.cpp
Normal file
File diff suppressed because it is too large
Load Diff
182
neo/d3xp/IK.h
Normal file
182
neo/d3xp/IK.h
Normal 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
2138
neo/d3xp/Item.cpp
Normal file
File diff suppressed because it is too large
Load Diff
324
neo/d3xp/Item.h
Normal file
324
neo/d3xp/Item.h
Normal 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
332
neo/d3xp/Leaderboards.cpp
Normal 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
74
neo/d3xp/Leaderboards.h
Normal 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
1182
neo/d3xp/Light.cpp
Normal file
File diff suppressed because it is too large
Load Diff
142
neo/d3xp/Light.h
Normal file
142
neo/d3xp/Light.h
Normal 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
3934
neo/d3xp/Misc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
928
neo/d3xp/Misc.h
Normal file
928
neo/d3xp/Misc.h
Normal 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
1355
neo/d3xp/Moveable.cpp
Normal file
File diff suppressed because it is too large
Load Diff
210
neo/d3xp/Moveable.h
Normal file
210
neo/d3xp/Moveable.h
Normal 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
4852
neo/d3xp/Mover.cpp
Normal file
File diff suppressed because it is too large
Load Diff
556
neo/d3xp/Mover.h
Normal file
556
neo/d3xp/Mover.h
Normal 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
3188
neo/d3xp/MultiplayerGame.cpp
Normal file
File diff suppressed because it is too large
Load Diff
357
neo/d3xp/MultiplayerGame.h
Normal file
357
neo/d3xp/MultiplayerGame.h
Normal 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
10742
neo/d3xp/Player.cpp
Normal file
File diff suppressed because it is too large
Load Diff
924
neo/d3xp/Player.h
Normal file
924
neo/d3xp/Player.h
Normal 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
190
neo/d3xp/PlayerIcon.cpp
Normal 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
65
neo/d3xp/PlayerIcon.h
Normal 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
1749
neo/d3xp/PlayerView.cpp
Normal file
File diff suppressed because it is too large
Load Diff
417
neo/d3xp/PlayerView.h
Normal file
417
neo/d3xp/PlayerView.h
Normal 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
78
neo/d3xp/PredictedValue.h
Normal 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
|
||||
220
neo/d3xp/PredictedValue_impl.h
Normal file
220
neo/d3xp/PredictedValue_impl.h
Normal 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
2989
neo/d3xp/Projectile.cpp
Normal file
File diff suppressed because it is too large
Load Diff
339
neo/d3xp/Projectile.h
Normal file
339
neo/d3xp/Projectile.h
Normal 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
1421
neo/d3xp/Pvs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
126
neo/d3xp/Pvs.h
Normal file
126
neo/d3xp/Pvs.h
Normal 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
587
neo/d3xp/SecurityCamera.cpp
Normal 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
97
neo/d3xp/SecurityCamera.h
Normal 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
438
neo/d3xp/SmokeParticles.cpp
Normal 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
103
neo/d3xp/SmokeParticles.h
Normal 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
304
neo/d3xp/Sound.cpp
Normal 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
76
neo/d3xp/Sound.h
Normal 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
1921
neo/d3xp/Target.cpp
Normal file
File diff suppressed because it is too large
Load Diff
615
neo/d3xp/Target.h
Normal file
615
neo/d3xp/Target.h
Normal 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
1357
neo/d3xp/Trigger.cpp
Normal file
File diff suppressed because it is too large
Load Diff
312
neo/d3xp/Trigger.h
Normal file
312
neo/d3xp/Trigger.h
Normal 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
Reference in New Issue
Block a user