LYN-2537 engine assets (#254)

* LYN-2537 Moved the Engine and Editor folder to be within the EngineAssets folder

* Fixed Documentation in bootstrap.cfg to correct the path to the user project specific registry file

* Adding a newline to the output of AssetCatalog 'Registering asset..., but type is not set' message

* Updating the AssetProcessorPlatformConfig.setreg Scan Folder to detect
the @ENGINEROOT@/EngineAssets/Engine path for engine runtime assets and
@ENGINEROOT@/EngineAssets/Editor path for engine tool assets

* Updating references to Icons and other assets to account for moving the
Engine and Editor folder under a single EngineAssets folder

* Moving the Engine Settings Registry folder from Engine/Registry -> Registry

* Removed the LY_PROJECT_CMAKE_PATH define as it is not portable to other locations. It is hard coded to the project location that was used for the CMake configuration. Furthermore it paths with backslashes within it are treated as escape characters and not a path separator

* Updated the LyTestTools asset_processor.py script to copy the exclude.filetag from the EngineAssets/Engine directory now

* Fixed Atom Shader Preprocessing when running using an External Project

* Updated the TSGenerateAction.cpp to fix the build error with using a renamed variable

* Updated the Install_Common.cmake ly_setup_others function to install the
EngineAssets directory and the each of the Gem's Assets directory while
maintaining the relative directory structure to the Engine Root
Also updated the install step to install the Registry folder at the
engine root

* Fixed the copying of the Registry folder to be in the install root, instead of under a second 'Registry' folder

* Moving the AssetProcessorPlatformConfig.setreg file over to the Registry folder

* Updated the LyTestTools and C++ code to point that the new location of
the AssetProcessorPlatformConfig.setreg file inside of the Registry
folder

* Renamed Test AssetProcessor*Config.ini files to have the .setreg extension

* Converted the AssetProcessor test setreg files from ini format to json
format using the SerializeContextTools convert-ini command

* Updated the AssetProcessor CMakeLists.txt to copy over the test setreg files to the build folder

* Updated the assetprocessor test file list to point at the renamed AsssetProcessor*Config setreg filenames

* Removed the Output Prefix code from the AssetProcessor. The complexity that it brought to the AP code is not needed, as users can replicate the behavior by just moving there assets underneath a another folder, underneath the scan folder

* Adding back support to read the AssetProcessorPlatformConfig.setreg file from the asset root. This is only needed for C++ UnitTests as they run in an environment where the accessing the Engine Settings Registry is not available

* Updating the Install_common.cmake logic to copy any "Assets" folder to
the install layout.
The Script has also been updated to copy over the "Assets" folder in the
Engine Root to the install layout instead of an "EngineAssets" folder

* Updating References to EngineAssets source asset folder in code to be the Assets source folder

* Moved the Engine Source Asset folder of 'EngineAssets' to a new folder name of 'Assets'. This is inline with the naming scheme we use for Gem asset folders

* Adding the EngineFinder.cmake to the AutomatedTesting project to allow it to work in a project centric manner

* Updating the LyTestTools copy_assets_to_project function to be able to copy assets with folders to the temporary project root
Fixed an issue in LyTestTools where the temporary log directory could have shutil.rmtree being called twice on it leading to an exception which fails an automated test

Updated the asset_procesor_gui_tests_2 AddScanFolder test to not use the
output prefix, but instead place the source asset root into a
subdirectory

* Correct the AssetProcessorPlatformConfig Scan Folders for the EngineAssets directory to point at the Assets directory

* Updated the asset procesor batch dependency test scan folder to point at the 'Assets' folder instead of 'EngineAssets'
This commit is contained in:
lumberyard-employee-dm
2021-04-28 21:38:43 -05:00
committed by GitHub
parent ed74bb9166
commit 3dec5d3b71
2087 changed files with 1208 additions and 3655 deletions
@@ -0,0 +1,25 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
NavigationSeedPoint = {
type = "NavigationSeedPoint",
Editor = {
Icon = "Seed.bmp",
},
}
-------------------------------------------------------
function NavigationSeedPoint:OnInit()
CryAction.RegisterWithAI(self.id, AIOBJECT_NAV_SEED);
end
@@ -0,0 +1,65 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
-- Original file Copyright Crytek GMBH or its affiliates, used under license.
--
----------------------------------------------------------------------------------------------------
SmartObject = {
type = "SmartObject",
Properties =
{
soclasses_SmartObjectClass = "",
},
Editor={
Model="Editor/Objects/anchor.cgf",
Icon="smartobject.bmp",
IconOnTop=1,
},
}
-------------------------------------------------------
function SmartObject:OnInit()
end
-------------------------------------------------------
function SmartObject:OnReset()
end
-------------------------------------------------------
function SmartObject:OnUsed()
-- this function will be called from ACT_USEOBJECT
BroadcastEvent(self, "Used");
end
-------------------------------------------------------
function SmartObject:OnNavigationStarted(userId)
self:ActivateOutput("NavigationStarted", userId or NULL_ENTITY)
end
-------------------------------------------------------
function SmartObject:Event_Used( sender )
BroadcastEvent(self, "Used");
end
SmartObject.FlowEvents =
{
Inputs =
{
Used = { SmartObject.Event_Used, "bool" },
},
Outputs =
{
Used = "bool",
NavigationStarted = "entity",
},
}
@@ -0,0 +1,31 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
TagPoint = {
type = "TagPoint",
Editor = {
Icon = "TagPoint.bmp",
},
}
-------------------------------------------------------
function TagPoint:OnSpawn()
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
-------------------------------------------------------
function TagPoint:OnInit()
CryAction.RegisterWithAI(self.id, AIOBJECT_WAYPOINT);
end
@@ -0,0 +1,33 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
-- Just here so the entity system won't spam
CActorWrapper =
{
Editor={
Icon="SpawnPoint.bmp",
},
Properties =
{
Prototype = ""
},
}
function CActorWrapper:OnSpawn()
CryAction.CreateGameObjectForEntity(self.id);
CryAction.ActivateExtensionForGameObject(self.id, "CActorWrapper", true);
end
function CActorWrapper:OnDestroy()
CryAction.ActivateExtensionForGameObject(self.id, "CActorWrapper", false);
end
@@ -0,0 +1,40 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
-- Original file Copyright Crytek GMBH or its affiliates, used under license.
--
--
--
----------------------------------------------------------------------------------------------------
MannequinObject =
{
Properties =
{
objModel = "",
fileActionController = "",
fileAnimDatabase3P = "",
},
Editor =
{
Icon = "user.bmp",
IconOnTop = 1,
},
}
function MannequinObject:OnPropertyChange()
-- The OnPropertyChange callback is forwarded to script directly by the editor.
-- As most of this entity is written in C++, we just want to send a notification
-- that a property has changed, and deal with it there.
self:ProcessBroadcastEvent( "OnPropertyChange" );
end
@@ -0,0 +1,110 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
Script.ReloadScript("scripts/Utils/EntityUtils.lua")
GeomEntity =
{
Client = {},
Server = {},
Editor={
Icon="physicsobject.bmp",
IconOnTop=1,
}
}
--------------------------------------------------------------------------
function GeomEntity.Server:OnInit()
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
--------------------------------------------------------------------------
function GeomEntity.Client:OnInit()
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
------------------------------------------------------------------------------------------------------
function GeomEntity:OnPhysicsBreak( vPos,nPartId,nOtherPartId )
self:ActivateOutput("Break",nPartId+1 );
end
------------------------------------------------------------------------------------------------------
function GeomEntity:Event_Remove()
self:DrawSlot(0,0);
self:DestroyPhysics();
self:ActivateOutput( "Remove", true );
end
------------------------------------------------------------------------------------------------------
function GeomEntity:Event_Hide()
self:Hide(1);
self:ActivateOutput( "Hide", true );
end
------------------------------------------------------------------------------------------------------
function GeomEntity:Event_UnHide()
self:Hide(0);
self:ActivateOutput( "UnHide", true );
end
function GeomEntity:OnLoad(table)
self.health = table.health;
self.dead = table.dead;
if(table.bAnimateOffScreenShadow) then
self.bAnimateOffScreenShadow = table.bAnimateOffScreenShadow;
else
self.bAnimateOffScreenShadow = false;
end
end
function GeomEntity:OnSave(table)
table.health = self.health;
table.dead = self.dead;
if(self.bAnimateOffScreenShadow) then
table.bAnimateOffScreenShadow = self.bAnimateOffScreenShadow;
else
table.bAnimateOffScreenShadow = false;
end
end
-------------------------------------------------------
function GeomEntity:OnPropertyChange()
self:OnReset();
end
GeomEntity.FlowEvents =
{
Inputs =
{
Hide = { GeomEntity.Event_Hide, "bool" },
UnHide = { GeomEntity.Event_UnHide, "bool" },
Remove = { GeomEntity.Event_Remove, "bool" },
},
Outputs =
{
Hide = "bool",
UnHide = "bool",
Remove = "bool",
Break = "int",
},
}
MakeTargetableByAI(GeomEntity);
MakeKillable(GeomEntity);
MakeRenderProxyOptions(GeomEntity);
@@ -0,0 +1,109 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
Script.ReloadScript("scripts/Utils/EntityUtils.lua")
RopeEntity =
{
Properties=
{
MultiplayerOptions = {
bNetworked = 0,
},
},
}
------------------------------------------------------------------------------------------------------
function RopeEntity:OnSpawn()
if (self.Properties.MultiplayerOptions.bNetworked == 0) then
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
end
------------------------------------------------------------------------------------------------------
function RopeEntity:OnPhysicsBreak( vPos,nPartId,nOtherPartId )
self:ActivateOutput("Break",nPartId+1 );
end
------------------------------------------------------------------------------------------------------
function RopeEntity:Event_Remove()
self:DrawSlot(0,0);
self:DestroyPhysics();
self:ActivateOutput( "Remove", true );
end
------------------------------------------------------------------------------------------------------
function RopeEntity:Event_Hide()
self:Hide(1);
self:ActivateOutput( "Hide", true );
end
------------------------------------------------------------------------------------------------------
function RopeEntity:Event_UnHide()
self:Hide(0);
self:ActivateOutput( "UnHide", true );
end
------------------------------------------------------------------------------------------------------
function RopeEntity:Event_BreakStart( vPos,nPartId,nOtherPartId )
local RopeParams = {}
RopeParams.entity_name_1 = "#unattached";
self:SetPhysicParams(PHYSICPARAM_ROPE,RopeParams);
end
function RopeEntity:Event_BreakEnd( vPos,nPartId,nOtherPartId )
local RopeParams = {}
RopeParams.entity_name_2 = "#unattached";
self:SetPhysicParams(PHYSICPARAM_ROPE,RopeParams);
end
function RopeEntity:Event_BreakDist( sender, dist )
local RopeParams = {}
RopeParams.break_point = dist;
self:SetPhysicParams(PHYSICPARAM_ROPE,RopeParams);
end
function RopeEntity:Event_Disable()
local RopeParams = {}
RopeParams.bDisabled = 1;
self:SetPhysicParams(PHYSICPARAM_ROPE,RopeParams);
end
function RopeEntity:Event_Enable()
local RopeParams = {}
RopeParams.bDisabled = 0;
self:SetPhysicParams(PHYSICPARAM_ROPE,RopeParams);
end
RopeEntity.FlowEvents =
{
Inputs =
{
Hide = { RopeEntity.Event_Hide, "bool" },
UnHide = { RopeEntity.Event_UnHide, "bool" },
Remove = { RopeEntity.Event_Remove, "bool" },
BreakStart = { RopeEntity.Event_BreakStart, "bool" },
BreakEnd = { RopeEntity.Event_BreakEnd, "bool" },
BreakDist = { RopeEntity.Event_BreakDist, "float" },
Disable = { RopeEntity.Event_Disable, "bool" },
Enable = { RopeEntity.Event_Enable, "bool" },
},
Outputs =
{
Hide = "bool",
UnHide = "bool",
Remove = "bool",
Break = "int",
},
}
@@ -0,0 +1,110 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
WaterVolume =
{
type = "WaterVolume",
Properties =
{
StreamSpeed = 0,
FogDensity = 0.5,
color_FogColor = {x=0.005,y=0.01,z=0.02},
FogColorMultiplier = 0.5,
bFogColorAffectedBySun = 1,
FogShadowing = 0.5,
bCapFogAtVolumeDepth = 0,
bCaustics = 1,
CausticIntensity = 1,
CausticTiling = 1,
CausticHeight = 0.5,
UScale = 1,
VScale = 1,
Depth = 5,
ViewDistancemMultiplier = 1.0,
MinSpec = 0,
MaterialLayerMask = 0,
bAwakeAreaWhenMoving = 0, --[0,1,1,"Entities in area are physically awake when game volume is moving"]
bIsRiver = 0,
MultiplayerOptions =
{
bNetworked = 0,
},
},
Editor =
{
Model = "Editor/Objects/T.cgf",
Icon = "Water.bmp",
ShowBounds = 1,
IsScalable = false;
IsRotatable = true;
},
}
-------------------------------------------------------------------------------------------------------
function WaterVolume:OnSpawn()
if (self.Properties.MultiplayerOptions.bNetworked == 0) then
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
end
-------------------------------------------------------------------------------------------------------
function WaterVolume:OnPropertyChange()
end
-------------------------------------------------------------------------------------------------------
function WaterVolume:IsShapeOnly()
return 1;
end
-------------------------------------------------------------------------------------------------------
function WaterVolume:Event_Hide()
self:Hide(1);
self:ActivateOutput( "Hidden", true );
end;
-------------------------------------------------------------------------------------------------------
function WaterVolume:Event_UnHide()
self:Hide(0);
self:ActivateOutput( "UnHidden", true );
end;
-------------------------------------------------------------------------------------------------------
function WaterVolume:Event_PhysicsEnable()
Game.SendEventToGameObject( self.id, "PhysicsEnable" );
end;
-------------------------------------------------------------------------------------------------------
function WaterVolume:Event_PhysicsDisable()
Game.SendEventToGameObject( self.id, "PhysicsDisable" );
end;
WaterVolume.FlowEvents =
{
Inputs =
{
Hide = { WaterVolume.Event_Hide, "bool" },
UnHide = { WaterVolume.Event_UnHide, "bool" },
PhysicsEnable = { WaterVolume.Event_PhysicsEnable, "bool" },
PhysicsDisable = { WaterVolume.Event_PhysicsDisable, "bool" },
},
Outputs =
{
Hidden = "bool",
UnHidden = "bool",
},
}
@@ -0,0 +1,251 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
Script.ReloadScript("Scripts/Entities/Lights/Light.lua")
EnvironmentLight =
{
Properties =
{
_nVersion = -1,
bActive = 0,
BoxSizeX = 10,
BoxSizeY = 10,
BoxSizeZ = 10,
Color =
{
clrDiffuse = { x=1,y=1,z=1 },
fDiffuseMultiplier = 1,
fSpecularMultiplier = 1,
},
Projection =
{
bBoxProject = 0,
fBoxWidth = 10,
fBoxHeight = 10,
fBoxLength = 10,
},
Options =
{
bAffectsThisAreaOnly = 1,
bIgnoresVisAreas = 0,
bDeferredClipBounds = 0,
_texture_deferred_cubemap = "",
SortPriority = 0,
fAttenuationFalloffMax = 0.3,
bVolumetricFog = 1, --[0,1,1,"Enables the light to affect volumetric fog."]
bAffectsVolumetricFogOnly = 0, --[0,1,0,"Enables the light to affect only volumetric fog."]
},
OptionsAdvanced =
{
texture_deferred_cubemap = "",
},
},
Editor =
{
ShowBounds = 0,
AbsoluteRadius = 1,
},
_LightTable = {},
}
LightSlot = 1
function EnvironmentLight:OnInit()
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY, 0);
self:OnReset();
self:Activate(1); -- Force OnUpdate to get called
self:CacheResources("EnvironmentLight.lua");
end
function EnvironmentLight:CacheResources(requesterName)
if ( self.Properties.OptionsAdvanced.texture_deferred_cubemap == "" ) then
self.Properties.OptionsAdvanced.texture_deferred_cubemap = self.Properties.Options._texture_deferred_cubemap;
end
end
function EnvironmentLight:OnShutDown()
self:FreeSlot(LightSlot);
end
function EnvironmentLight:OnLoad(props)
self:OnReset()
self:ActivateLight(props.bActive)
end
function EnvironmentLight:OnSave(props)
props.bActive = self.bActive
end
function EnvironmentLight:OnLevelLoaded()
if (self.Properties.Options.bDeferredClipBounds) then
self:UpdateLightClipBounds(LightSlot);
end
end
function EnvironmentLight:OnPropertyChange()
self:OnReset();
self:ActivateLight( self.bActive );
if (self.Properties.Options.bAffectsThisAreaOnly == 1) then
self:UpdateLightClipBounds(LightSlot);
end
end
-- optimization for common animated trackview properties, to avoid fully recreating everything on every animated frame
function EnvironmentLight:OnPropertyAnimated( name )
local changeTakenCareOf = false;
if (name=="fDiffuseMultiplier" or name=="fSpecularMultiplier") then
changeTakenCareOf = true;
local Color = self.Properties.Color;
local diffuse_mul = Color.fDiffuseMultiplier;
local specular_multiplier = Color.fSpecularMultiplier;
local diffuse_color = { x=Color.clrDiffuse.x*diffuse_mul, y=Color.clrDiffuse.y*diffuse_mul, z=Color.clrDiffuse.z*diffuse_mul };
self:SetLightColorParams( LightSlot, diffuse_color, specular_multiplier);
end
return changeTakenCareOf;
end
function EnvironmentLight:OnUpdate(dt)
if (self.bActive == 1 and self.Properties.Options.bAffectsThisAreaOnly == 1) then
self:UpdateLightClipBounds(LightSlot);
end
if (not System.IsEditor()) then
self:Activate(0);
end
end
function EnvironmentLight:OnReset()
if (self.bActive ~= self.Properties.bActive) then
self:ActivateLight( self.Properties.bActive );
end
end
function EnvironmentLight:ActivateLight( enable )
if (enable and enable ~= 0) then
self.bActive = 1;
self:LoadLightToSlot(LightSlot);
self:ActivateOutput( "Active",true );
else
self.bActive = 0;
self:FreeSlot(LightSlot);
self:ActivateOutput( "Active",false );
end
end
function EnvironmentLight:LoadLightToSlot( nSlot )
local props = self.Properties;
local Color = props.Color;
local Options = props.Options;
local OptionsAdvanced = props.OptionsAdvanced;
local Projection = props.Projection;
local diffuse_mul = Color.fDiffuseMultiplier;
local specular_mul = Color.fSpecularMultiplier;
local lt = self._LightTable;
lt.radius = 0.5 * (props.BoxSizeX*props.BoxSizeX + props.BoxSizeY*props.BoxSizeY + props.BoxSizeZ*props.BoxSizeZ) ^ 0.5;
lt.box_size_x = props.BoxSizeX;
lt.box_size_y = props.BoxSizeY;
lt.box_size_z = props.BoxSizeZ;
lt.diffuse_color = { x=Color.clrDiffuse.x*diffuse_mul, y=Color.clrDiffuse.y*diffuse_mul, z=Color.clrDiffuse.z*diffuse_mul };
lt.specular_multiplier = specular_mul;
if ( OptionsAdvanced.texture_deferred_cubemap == "" ) then
OptionsAdvanced.texture_deferred_cubemap = Options._texture_deferred_cubemap;
end
lt.deferred_cubemap = OptionsAdvanced.texture_deferred_cubemap;
lt.this_area_only = Options.bAffectsThisAreaOnly;
lt.ignore_visareas = Options.bIgnoresVisAreas;
lt.volumetric_fog = Options.bVolumetricFog;
lt.volumetric_fog_only = Options.bAffectsVolumetricFogOnly;
lt.box_projection = Projection.bBoxProject; -- settings for box projection
lt.box_width = Projection.fBoxWidth;
lt.box_height = Projection.fBoxHeight;
lt.box_length = Projection.fBoxLength;
lt.sort_priority = Options.SortPriority;
lt.attenuation_falloff_max = Options.fAttenuationFalloffMax;
lt.lightmap_linear_attenuation = 1;
lt.is_rectangle_light = 0;
lt.is_sphere_light = 0;
lt.area_sample_number = 1;
lt.RAE_AmbientColor = { x = 0, y = 0, z = 0 };
lt.RAE_MaxShadow = 1;
lt.RAE_DistMul = 1;
lt.RAE_DivShadow = 1;
lt.RAE_ShadowHeight = 1;
lt.RAE_FallOff = 2;
lt.RAE_VisareaNumber = 0;
self:LoadLight( nSlot,lt );
end
function EnvironmentLight:Event_Enable()
if (self.bActive == 0) then
self:ActivateLight( 1 );
end
end
function EnvironmentLight:Event_Disable()
if (self.bActive == 1) then
self:ActivateLight( 0 );
end
end
function Light:NotifySwitchOnOffFromParent(wantOn)
local wantOff = wantOn~=true;
if (self.bActive == 1 and wantOff) then
self:ActivateLight( 0 );
elseif (self.bActive == 0 and wantOn) then
self:ActivateLight( 1 );
end
end
------------------------------------------------------------------------------------------------------
-- Event Handlers
------------------------------------------------------------------------------------------------------
function EnvironmentLight:Event_Active( bActive )
if (self.bActive == 0 and bActive == true) then
self:ActivateLight( 1 );
else
if (self.bActive == 1 and bActive == false) then
self:ActivateLight( 0 );
end
end
end
------------------------------------------------------------------------------------------------------
-- Event descriptions.
------------------------------------------------------------------------------------------------------
EnvironmentLight.FlowEvents =
{
Inputs =
{
Active = { EnvironmentLight.Event_Active,"bool" },
Enable = { EnvironmentLight.Event_Enable,"bool" },
Disable = { EnvironmentLight.Event_Disable,"bool" },
},
Outputs =
{
Active = "bool",
},
}
@@ -0,0 +1,277 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
Light =
{
Properties =
{
_nVersion = -1,
bActive = 1, --[0,1,1,"Turns the light on/off."]
Radius = 10, --[0,100,1,"Specifies how far from the source the light affects the surrounding area."]
fAttenuationBulbSize = 0.05, --[0,100,0.1,"Specifies the radius of the area light bulb."]
Style =
{
nLightStyle = 0, --[0,50,1,"Specifies a preset animation for the light to play."]
fAnimationSpeed = 1, --[0,100,0.1,"Specifies the speed at which the light animation should play."]
nAnimationPhase = 0, --[0,100,1,"This will start the light style at a different point along the sequence."]
bAttachToSun = 0, --[0,1,1,"When enabled, sets the Sun to use the Flare properties for this light."]
lightanimation_LightAnimation = "",
bTimeScrubbingInTrackView = 0,
_fTimeScrubbed = 0,
bFlareEnable = 1, --[0,1,1,"Toggles the flare effect on or off for this light."]
flare_Flare = "",
fFlareFOV = 360, --[0,360,1,"FOV for the flare."]
},
Projector =
{
texture_Texture = "",
fProjectorFov = 90, --[0,180,1,"Specifies the Angle on which the light texture is projected."]
fProjectorNearPlane = 0, --[-100,100,0.1,"Set the near plane for the projector, any surfaces closer to the light source than this value will not be projected on."]
},
Color =
{
clrDiffuse = { x=1,y=1,z=1 },
fDiffuseMultiplier = 1, --[0,999,0.1,"Control the strength of the diffuse color."]
fSpecularMultiplier = 1, --[0,999,0.1,"Control the strength of the specular brightness."]
},
Options =
{
bAffectsThisAreaOnly = 1, --[0,1,1,"Set this parameter to false to make light cast in multiple visareas."]
bIgnoresVisAreas = 0, --[0,1,1,"Controls whether the light should respond to visareas."]
bAmbient = 0, --[0,1,1,"Makes the light behave like an ambient light source, with no point of origin."]
bFakeLight = 0, --[0,1,1,"Disables light projection, useful for lights which you only want to have Flare effects from."]
bVolumetricFog = 1, --[0,1,1,"Enables the light to affect volumetric fog."]
bAffectsVolumetricFogOnly = 0, --[0,1,0,"Enables the light to affect only volumetric fog."]
fFogRadialLobe = 0, --[0,1,0,"Set the blend ratio of main and side radial lobe for volumetric fog."]
},
Shadows =
{
nCastShadows = 0,
fShadowBias = 1, --[0,1000,1,"Moves the shadow cascade toward or away from the shadow-casting object."]
fShadowSlopeBias = 1, --[0,1000,1,"Allows you to adjust the gradient (slope-based) bias used to compute the shadow bias."]
fShadowResolutionScale = 1,
nShadowMinResPercent = 0, --[0,100,1,"Percentage of the shadow pool the light should use for its shadows."]
fShadowUpdateMinRadius = 10, --[0,100,0.1,"Define the minimum radius from the light source to the player camera that the ShadowUpdateRatio setting will be ignored."]
fShadowUpdateRatio = 1, --[0,10,0.01,"Define the update ratio for shadow maps cast from this light."]
},
Shape =
{
bAreaLight = 0, --[0,1,1,"Used to turn the selected light entity into a Rectangular Area Light."]
fPlaneWidth = 1, --[0,100,0.1,"Set the width of the Area Light shape."]
fPlaneHeight = 1, --[0,100,0.1,"Set the height of the Area Light shape."]
},
},
Editor =
{
Model="Editor/Objects/Light_Omni.cgf",
Icon="Light.bmp",
ShowBounds=0,
AbsoluteRadius = 1,
IsScalable = false;
},
_LightTable = {},
}
LightSlot = 1
function Light:OnInit()
--self:NetPresent(0);
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY, 0);
self:OnReset();
self:CacheResources("Light.lua");
end
function Light:CacheResources(requesterName)
local textureFlags = 0;
end
function Light:OnShutDown()
self:FreeSlot(LightSlot);
end
function Light:OnLoad(props)
self:OnReset()
self:ActivateLight(props.bActive)
end
function Light:OnSave(props)
props.bActive = self.bActive
end
function Light:OnPropertyChange()
self:OnReset();
self:ActivateLight( self.bActive );
if (self.Properties.Options.bAffectsThisAreaOnly == 1) then
self:UpdateLightClipBounds(LightSlot);
end
end
-- Optimization for common animated trackview properties, to avoid fully recreating everything on every animated frame
function Light:OnPropertyAnimated( name )
local changeTakenCareOf = false;
if (name=="fDiffuseMultiplier" or name=="fSpecularMultiplier") then
changeTakenCareOf = true;
local Color = self.Properties.Color;
local diffuse_mul = Color.fDiffuseMultiplier;
local specular_multiplier = Color.fSpecularMultiplier;
local diffuse_color = { x=Color.clrDiffuse.x*diffuse_mul, y=Color.clrDiffuse.y*diffuse_mul, z=Color.clrDiffuse.z*diffuse_mul };
self:SetLightColorParams( LightSlot, diffuse_color, specular_multiplier);
end
return changeTakenCareOf;
end
function Light:OnSysSpecLightChanged()
self:OnPropertyChange();
end
function Light:OnLevelLoaded()
if (self.Properties.Options.bAffectsThisAreaOnly == 1) then
self:UpdateLightClipBounds(LightSlot);
end
end
function Light:OnReset()
if (self.bActive ~= self.Properties.bActive) then
self:ActivateLight( self.Properties.bActive );
end
end
function Light:ActivateLight( enable )
if (enable and enable ~= 0) then
self.bActive = 1;
self:LoadLightToSlot(LightSlot);
self:ActivateOutput( "Active",true );
else
self.bActive = 0;
self:FreeSlot(LightSlot);
self:ActivateOutput( "Active",false );
end
end
function Light:LoadLightToSlot( nSlot )
local props = self.Properties;
local Style = props.Style;
local Projector = props.Projector;
local Color = props.Color;
local Options = props.Options;
local Shape = props.Shape;
local Shadows = props.Shadows;
local diffuse_mul = Color.fDiffuseMultiplier;
local specular_mul = Color.fSpecularMultiplier;
local lt = self._LightTable;
lt.radius = props.Radius;
lt.attenuation_bulbsize = props.fAttenuationBulbSize;
lt.diffuse_color = { x=Color.clrDiffuse.x*diffuse_mul, y=Color.clrDiffuse.y*diffuse_mul, z=Color.clrDiffuse.z*diffuse_mul };
lt.specular_multiplier = specular_mul;
lt.this_area_only = Options.bAffectsThisAreaOnly;
lt.ambient = props.Options.bAmbient;
lt.fake = Options.bFakeLight;
lt.ignore_visareas = Options.bIgnoresVisAreas;
lt.volumetric_fog = Options.bVolumetricFog;
lt.volumetric_fog_only = Options.bAffectsVolumetricFogOnly;
lt.fog_radial_lobe = Options.fFogRadialLobe;
lt.cast_shadow = Shadows.nCastShadows;
lt.shadow_bias = Shadows.fShadowBias;
lt.shadow_slope_bias = Shadows.fShadowSlopeBias;
lt.shadowResolutionScale = Shadows.fShadowResolutionScale;
lt.shadowMinResolution = Shadows.nShadowMinResPercent;
lt.shadowUpdate_MinRadius = Shadows.fShadowUpdateMinRadius;
lt.shadowUpdate_ratio = Shadows.fShadowUpdateRatio;
lt.projector_texture = Projector.texture_Texture;
lt.proj_fov = Projector.fProjectorFov;
lt.proj_nearplane = Projector.fProjectorNearPlane;
lt.area_light = Shape.bAreaLight;
lt.area_width = Shape.fPlaneWidth;
lt.area_height = Shape.fPlaneHeight;
lt.style = Style.nLightStyle;
lt.attach_to_sun = Style.bAttachToSun;
lt.anim_speed = Style.fAnimationSpeed;
lt.anim_phase = Style.nAnimationPhase;
lt.light_animation = Style.lightanimation_LightAnimation;
lt.time_scrubbing_in_trackview = Style.bTimeScrubbingInTrackView;
lt.time_scrubbed = Style._fTimeScrubbed;
lt.flare_enable = Style.bFlareEnable;
lt.flare_Flare = Style.flare_Flare;
lt.flare_FOV = Style.fFlareFOV;
lt.lightmap_linear_attenuation = 1;
lt.is_rectangle_light = 0;
lt.is_sphere_light = 0;
lt.area_sample_number = 1;
lt.indoor_only = 0;
self:LoadLight( nSlot,lt );
end
function Light:Event_Enable()
if (self.bActive == 0) then
self:ActivateLight( 1 );
end
end
function Light:Event_Disable()
if (self.bActive == 1) then
self:ActivateLight( 0 );
end
end
function Light:NotifySwitchOnOffFromParent(wantOn)
local wantOff = wantOn~=true;
if (self.bActive == 1 and wantOff) then
self:ActivateLight( 0 );
elseif (self.bActive == 0 and wantOn) then
self:ActivateLight( 1 );
end
end
------------------------------------------------------------------------------------------------------
-- Event Handlers
------------------------------------------------------------------------------------------------------
function Light:Event_Active(sender, bActive)
if (self.bActive == 0 and bActive == true) then
self:ActivateLight( 1 );
else
if (self.bActive == 1 and bActive == false) then
self:ActivateLight( 0 );
end
end
end
------------------------------------------------------------------------------------------------------
-- Event descriptions
------------------------------------------------------------------------------------------------------
Light.FlowEvents =
{
Inputs =
{
Active = { Light.Event_Active,"bool" },
Enable = { Light.Event_Enable,"bool" },
Disable = { Light.Event_Disable,"bool" },
},
Outputs =
{
Active = "bool",
},
}
@@ -0,0 +1,24 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
CameraSource = {
Editor={
Icon="Camera.bmp",
},
};
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function CameraSource:OnInit()
self:CreateCameraComponent();
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
@@ -0,0 +1,15 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
CameraTarget = {
}
@@ -0,0 +1,214 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
-- Description: Comment system.
--
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
-- $Id$
-- $DateTime$
-- Description: Comment system.
--
----------------------------------------------------------------------------------------------------
Comment =
{
Properties =
{
Text = "This is a comment",
fSize = 1.2, --[0.0, 100.0 , 0.1, ""]
bHidden = 0,
fMaxDist = 100, --[0.0 ,255.0 , 0.1, ""]
nCharsPerLine = 30, --[1, 255, 1, ""]
bFixed = 0,
clrDiffuse = { x=1,y=0.5,z=0 },
},
Editor={
Model="Editor/Objects/comment.cgf",
Icon="Comment.bmp",
},
hidden = 0,
lines = {},
lineCount = 0,
fMaxDistSquared = 0,
bNoUpdateInGame = 1,
}
-------------------------------------------------------
function Comment:OnLoad(table)
self.hidden = table.hidden;
end
-------------------------------------------------------
function Comment:OnSave(table)
table.hidden = self.hidden;
end
-------------------------------------------------------
function Comment:OnInit()
-- Delete when not in dev-mode.
if (not System.IsDevModeEnable() ) then
self:DeleteThis();
return;
end
self:OnReset();
end
-------------------------------------------------------
function Comment:OnSpawn()
end
-------------------------------------------------------
function Comment:OnPropertyChange()
self:OnReset();
end
-------------------------------------------------------
function Comment:OnReset()
-- Comment is only Active(OnUpdate() will be called) when in Editor or when cl_comment > 0
local cl_comment = System.GetCVar("cl_comment")
if (System.IsEditor() or cl_comment > 0) then
self:SetUpdatePolicy( ENTITY_UPDATE_VISIBLE );
self:Activate(1)
else
self:Activate(0);
end
-- bNoUpdateInGame is checked in OnUpdate() to account for in-editor game mode.
if (cl_comment == 0) then
self.bNoUpdateInGame = 1;
else
self.bNoUpdateInGame = 0;
end
self.fMaxDistSquared = self.Properties.fMaxDist * self.Properties.fMaxDist;
self.hidden = self.Properties.bHidden;
self.lines = {};
-- process the text and line-break it
local maxLength = self.Properties.nCharsPerLine;
local curLength = 0;
local curText = "";
local curLine = 1;
for char in string.gfind(self.Properties.Text, ".") do
if (char == " ") then
-- word finished ... see if we are over the limit
if (curLength > maxLength) then
-- commit line
self.lines[curLine] = curText;
curLine = curLine + 1;
curText = "";
curLength = 0;
-- "consume" the whitespace
char = "";
end
end
if (char ~= "") then
-- append char
curText = curText..char;
curLength = curLength + 1;
end
end
self.lines[curLine] = curText;
self.lineCount = curLine;
self:OnUpdate(0);
end
-------------------------------------------------------
function Comment:OnUpdate(delta)
if (self.hidden ~= 0 or self:IsHidden() or self.Properties.Text =="" or (self.bNoUpdateInGame == 1 and not System.IsEditing())) then
return;
end
-- calculate alpha
local alpha = 0;
local factor = 0;
if (self.fMaxDistSquared>0) then
local mypos = g_Vectors.temp_v1;
self:GetWorldPos(mypos);
SubVectors(mypos, mypos, System.GetViewCameraPos());
local distSquared = LengthSqVector(mypos);
factor = distSquared;
if (self.Properties.fMaxDist >= 255.0) then
alpha = 1.0;
elseif (distSquared<self.fMaxDistSquared) then
alpha = distSquared/self.fMaxDistSquared;
alpha = 1.0 - alpha*alpha;
end
end
-- draw text
local increment = System.GetViewCameraUpDir();
if (alpha>0.001) then
local pos = self:GetWorldPos( g_Vectors.temp_v1 );
factor = math.sqrt(factor);
factor = (self.Properties.fSize/60) * factor * System.GetViewCameraFov();
local incrementAll = g_Vectors.temp_v4;
FastScaleVector(increment, increment, factor);
FastScaleVector(incrementAll, increment, (self.lineCount / 2 + 1));
-- start all the way at the top
FastSumVectors(pos, pos, incrementAll);
local textColor = { x=0, y=1, z=0 }; -- default color is for (bFixed == 1)
if (self.Properties.bFixed ~= 1) then
textColor = {x=self.Properties.clrDiffuse.x, y=self.Properties.clrDiffuse.y, z=self.Properties.clrDiffuse.z};
end
for i,val in ipairs(self.lines) do
System.DrawLabel( pos, self.Properties.fSize, val, textColor.x, textColor.y, textColor.z, alpha );
-- decrement the increment
FastDifferenceVectors(pos, pos, increment);
end
end
end
-------------------------------------------------------
function Comment:Event_UnHide(sender)
BroadcastEvent(self, "UnHide");
self.hidden = 0;
end
-------------------------------------------------------
function Comment:Event_Hide(sender)
BroadcastEvent(self, "Hide");
self.hidden = 1;
end
-------------------------------------------------------
Comment.FlowEvents =
{
Inputs =
{
Hide = { Comment.Event_Hide, "bool" },
UnHide = { Comment.Event_UnHide, "bool" },
},
Outputs =
{
Hide = "bool",
UnHide = "bool",
},
}
@@ -0,0 +1,128 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------
--
-- Description : Procedural object entity
--
-- Created by Marco C. May 2013
--
----------------------------------------------------------------------------
ProceduralObject = {
type = "ProceduralObject",
Properties = {
filePrefabLibrary= "",
ObjectVariation={
sPrefabVariation = "",
},
nMaxSpawn = 0,
},
-- editor information
Editor = {
Icon = "proceduralobject.bmp",
ShowBounds = 1,
},
PrefabSourceName = "",
--Client = {},
--Server = {},
}
function ProceduralObject:OnInit()
--System.Log( "OnInit proc object" );
self:OnReset();
end
function ProceduralObject:OnPropertyChange()
--System.Log( "OnPropertyChange" );
self:OnReset();
end
function ProceduralObject:OnDestroy( sender )
PrefabManager.Delete(self.id);
end
function ProceduralObject:OnMove()
--System.Log( "OnMove proc object" );
PrefabManager.Move(self.id);
end
function ProceduralObject:OnSpawn()
if (CryAction.IsClient()) then
--System.Log( "CLIENT" );
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
if (CryAction.IsServer()) then
--System.Log( "SERVER" );
self:SetFlags(ENTITY_FLAG_SERVER_ONLY,0);
end
end
function ProceduralObject:Spawn(seed)
--System.Log( "Spawning proc object" );
--System.Log( "PrefabName="..self.PrefabSourceName );
PrefabManager.Delete(self.id);
local props=self.Properties;
if(not EmptyString(props.filePrefabLibrary)) then
--System.Log( "Opening file:"..props.filePrefabLibrary);
PrefabManager.LoadLibrary(props.filePrefabLibrary);
if(not EmptyString(props.ObjectVariation.sPrefabVariation)) then
PrefabManager.Spawn(self.id,props.filePrefabLibrary,props.ObjectVariation.sPrefabVariation,seed,props.nMaxSpawn);
end
end
--System.Log( "PrefabName="..self.PrefabSourceName );
end
function ProceduralObject:OnHidden()
PrefabManager.Hide(self.id,true);
end
function ProceduralObject:OnUnHidden()
PrefabManager.Hide(self.id,false);
end
function ProceduralObject:OnReset( sender )
--System.Log( "OnReset" );
if (System.IsEditor()) then
-- change prefabs only if we are editing (and the user pressed reload script),
-- do not change every time we go in and out of game mode...
-- unless we are in game mode generation
local clientgamemode=0; --System.GetCVar("g_GameModeGenerate");
if (System.IsEditing() or clientgamemode==1) then
PrefabManager.Delete(self.id);
self:Spawn(0);
end
else
PrefabManager.Delete(self.id);
end
--System.Log( "OnReset done" );
end
@@ -0,0 +1,208 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
RigidBody = {
type = "RigidBody",
MapVisMask = 0,
Properties = {
soclasses_SmartObjectClass = "",
bAutoGenAIHidePts = 0,
objModel = "Objects/box.cgf",
Density = 5000,
Mass = 1,
bResting = 1, -- If rigid body is originally in resting state.
bVisible = 1, -- If rigid body is originally visible.
bRigidBodyActive = 1, -- If rigid body is originally created OR will be created only on OnActivate.
bActivateOnRocketDamage = 0, -- Activate when a rocket hit the entity.
Impulse = {X=0,Y=0,Z=0}, -- Impulse to apply at event.
max_time_step = 0.01,
sleep_speed = 0.04,
damping = 0,
water_damping = 1.5,
water_resistance = 0,
},
temp_vec={x=0,y=0,z=0},
PhysParams = { mass=0,density=0 },
updateTime = 500,
gravityUpdate = 0,
Editor={
Icon = "physicsobject.bmp",
IconOnTop=1,
},
}
-------------------------------------------------------
function RigidBody:OnInit()
self.ModelName = "";
self.Mass = 0;
self:OnReset();
-- System.Log( "here1" );
end
-------------------------------------------------------
function RigidBody:OnReset()
--self:NetPresent(nil);
if (self.ModelName ~= self.Properties.objModel or self.Mass ~= self.Properties.Mass) then
self.Mass = self.Properties.Mass;
self.ModelName = self.Properties.objModel;
self:LoadObject( 0,self.ModelName );
end
local Properties = self.Properties;
if (Properties.bVisible == 0) then
self:DrawSlot( 0,0 );
else
self:DrawSlot( 0,1 );
end
local physType;
if (self.Properties.bRigidBodyActive == 1) then
physType = PE_RIGID;
self.PhysParams.density = Properties.Density;
self.PhysParams.mass = Properties.Mass;
else
physType = PE_STATIC;
end
self:Physicalize( 0,physType,self.PhysParams );
self:SetPhysicParams(PHYSICPARAM_SIMULATION, self.Properties );
self:SetPhysicParams(PHYSICPARAM_BUOYANCY, self.Properties );
if (self.Properties.bResting == 0) then
self:AwakePhysics(1);
else
self:AwakePhysics(0);
end
-- Mark AI hideable flag.
if (self.Properties.bAutoGenAIHidePts == 1) then
self:SetFlags(ENTITY_FLAG_AI_HIDEABLE, 0); -- set
else
self:SetFlags(ENTITY_FLAG_AI_HIDEABLE, 2); -- remove
end
end
-------------------------------------------------------
function RigidBody:OnPropertyChange()
self:OnReset();
end
-------------------------------------------------------
function RigidBody:OnContact( player )
self:Event_OnTouch( player );
end
-------------------------------------------------------
function RigidBody:OnDamage( hit )
--System.LogToConsole( "On Damage" );
if( hit.ipart ) then
self:AddImpulse( hit.ipart, hit.pos, hit.dir, hit.impact_force_mul );
-- else
-- self:AddImpulse( -1, hit.pos, hit.dir, hit.impact_force_mul );
end
if(self.Properties.bActivateOnRocketDamage)then
if(hit.explosion)then
self:AwakePhysics(1);
end
end
end
-------------------------------------------------------
function RigidBody:OnShutDown()
end
-------------------------------------------------------
function RigidBody:OnTimer()
-- System.Log("RigidBody OnTimer");
-- self:SetTimer( 0,1000 );
end
function RigidBody:OnUpdate()
--FIXME: all this timing stuff will be replaced by OnTimer once it will work again
self.gravityUpdate = self.gravityUpdate + _frametime;
if (self.gravityUpdate < 0.5) then
return;
end
self.gravityUpdate = 0.0;
EntityUpdateGravity(self);
end
-------------------------------------------------------
-- Input events
-------------------------------------------------------
function RigidBody:Event_AddImpulse(sender)
self.temp_vec.x=self.Properties.Impulse.X;
self.temp_vec.y=self.Properties.Impulse.Y;
self.temp_vec.z=self.Properties.Impulse.Z;
self:AddImpulse(0,nil,self.temp_vec,1);
end
-------------------------------------------------------
function RigidBody:Event_Activate(sender)
--create rigid body
self:CreateRigidBody( self.Properties.Density,self.Properties.Mass,0 );
self:Activate(1);
self:AwakePhysics(1);
end
-------------------------------------------------------
function RigidBody:Event_Show(sender)
self:DrawSlot( 0,1 );
end
-------------------------------------------------------
function RigidBody:Event_Hide(sender)
self:DrawSlot( 0,0 );
end
-------------------------------------------------------
-- Output events
-------------------------------------------------------
function RigidBody:Event_OnTouch(sender)
BroadcastEvent( self,"OnTouch" );
end
RigidBody.FlowEvents =
{
Inputs =
{
Activate = { RigidBody.Event_Activate, "bool" },
AddImpulse = { RigidBody.Event_AddImpulse, "bool" },
Hide = { RigidBody.Event_Hide, "bool" },
Show = { RigidBody.Event_Show, "bool" },
OnTouch = { RigidBody.Event_OnTouch, "bool" },
},
Outputs =
{
Activate = "bool",
AddImpulse = "bool",
Hide = "bool",
Show = "bool",
OnTouch = "bool",
},
}
@@ -0,0 +1,308 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
ParticleEffect = {
Properties = {
soclasses_SmartObjectClass = "",
ParticleEffect="",
Comment="",
bActive=1, -- Activate on startup
bPrime=1, -- Starts in equilibrium state, as if activated in past
Scale=1, -- Scale entire effect size.
SpeedScale=1, -- Scale particle emission speed
TimeScale=1, -- Scale emitter time evolution
CountScale=1, -- Scale particle counts.
bCountPerUnit=0, -- Multiply count by attachment extent
Strength=-1, -- Custom param control
esAttachType="", -- BoundingBox, Physics, Render
esAttachForm="", -- Vertices, Edges, Surface, Volume
PulsePeriod=0, -- Restart continually at this period.
NetworkSync=0, -- Do I want to be bound to the network?
bRegisterByBBox=0, -- Register In VisArea by BoundingBox, not by Position
Audio =
{
bEnableAudio=0, -- Toggles update of audio data.
audioRTPCRtpc="particlefx", -- The default audio RTPC name used.
}
},
Editor = {
Model="Editor/Objects/Particles.cgf",
Icon="Particles.bmp",
},
States = { "Active","Idle" },
Client = {},
Server = {},
};
Net.Expose {
Class = ParticleEffect,
ClientMethods = {
ClEvent_Spawn = { RELIABLE_ORDERED, POST_ATTACH },
ClEvent_Enable = { RELIABLE_ORDERED, POST_ATTACH },
ClEvent_Disable = { RELIABLE_ORDERED, POST_ATTACH },
ClEvent_Restart = { RELIABLE_ORDERED, POST_ATTACH },
ClEvent_Kill = { RELIABLE_ORDERED, POST_ATTACH },
},
ServerMethods = {
},
ServerProperties = {
},
};
-------------------------------------------------------
function ParticleEffect:OnSpawn()
if (not table.NetworkSync) then
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY, 0);
end
end
-------------------------------------------------------
function ParticleEffect:OnLoad(table)
self:GotoState(""); -- forces execution of either "Idle" or "Active" state constructor
if (not table.nParticleSlot) then
if (self.nParticleSlot) then
self:DeleteParticleEmitter( self.nParticleSlot );
end
self:GotoState("Idle");
elseif (not self.nParticleSlot or self.nParticleSlot ~= table.nParticleSlot) then
if (self.nParticleSlot) then
self:DeleteParticleEmitter( self.nParticleSlot );
end
self:GotoState("Idle");
self.nParticleSlot = self:LoadParticleEffect( table.nParticleSlot, self.Properties.ParticleEffect, self.Properties );
self:GotoState("Active");
end
end
-------------------------------------------------------
function ParticleEffect:OnSave(table)
table.nParticleSlot = self.nParticleSlot;
end
-------------------------------------------------------
function ParticleEffect:OnPropertyChange()
if self.Properties.bActive ~= 0 then
self:GotoState( "" );
self:GotoState( "Active" );
else
self:GotoState( "Idle" );
end
end
-------------------------------------------------------
function ParticleEffect:OnReset()
self:GotoState( "Idle" );
if self.Properties.bActive ~= 0 then
self:GotoState( "Active" );
end
end
------------------------------------------------------------------------------------------------------
function ParticleEffect:Event_Enable()
self:GotoState( "Active" );
self:ActivateOutput( "Enable", true );
if CryAction.IsServer() and self.allClients then
self.allClients:ClEvent_Enable();
end
end
function ParticleEffect:Event_Disable()
self:GotoState( "Idle" );
self:ActivateOutput( "Disable", true );
if CryAction.IsServer() and self.allClients then
self.allClients:ClEvent_Disable();
end
end
function ParticleEffect:Event_Restart()
self:GotoState( "Idle" );
self:GotoState( "Active" );
self:ActivateOutput( "Restart", true );
if CryAction.IsServer() and self.allClients then
self.allClients:ClEvent_Restart();
end
end
function ParticleEffect:Event_Spawn()
self:GetDirectionVector(1, g_Vectors.temp_v2); -- 1=forward vector
Particle.SpawnEffect( self.Properties.ParticleEffect, self:GetPos(g_Vectors.temp_v1), g_Vectors.temp_v2, self.Properties.Scale );
self:ActivateOutput( "Spawn", true );
if CryAction.IsServer() and self.allClients then
self.allClients:ClEvent_Spawn();
end
end
function ParticleEffect:Event_Kill()
if (self.nParticleSlot) then
self:DeleteParticleEmitter(self.nParticleSlot);
end;
self:GotoState( "Idle" );
if CryAction.IsServer() and self.allClients then
self.allClients:ClEvent_Kill();
end
end
function ParticleEffect:Enable()
self:GotoState("Active");
if CryAction.IsServer() and self.allClients then
self.allClients:ClEvent_Enable();
end
end
function ParticleEffect:Disable()
self:GotoState("Idle");
if CryAction.IsServer() and self.allClients then
self.allClients:ClEvent_Disable();
end
end
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Active State
-------------------------------------------------------------------------------
ParticleEffect.Active =
{
OnBeginState = function( self )
if not self.nParticleSlot then
self.nParticleSlot = -1;
end
self.nParticleSlot = self:LoadParticleEffect( self.nParticleSlot, self.Properties.ParticleEffect, self.Properties );
end,
OnLeaveArea = function( self,entity,areaId )
self:GotoState( "Idle" );
end,
}
-------------------------------------------------------------------------------
-- Idle State
-------------------------------------------------------------------------------
ParticleEffect.Idle =
{
OnBeginState = function( self )
if self.nParticleSlot then
self:FreeSlot(self.nParticleSlot);
self.nParticleSlot = nil;
end
end,
OnEnterArea = function( self,entity,areaId )
self:GotoState( "Active" );
end,
}
-- !!! net and states stuff
function ParticleEffect:DefaultState(cs, state)
local default = self[state];
self[cs][state] = {
OnBeginState = default.OnBeginState,
OnEndState = default.OnEndState,
OnLeaveArea = default.OnLeaveArea,
OnEnterArea = default.OnEnterArea,
}
end
-------------------------------------------------------
ParticleEffect:DefaultState("Server", "Idle");
ParticleEffect:DefaultState("Server", "Active");
ParticleEffect:DefaultState("Client", "Idle");
ParticleEffect:DefaultState("Client", "Active");
-------------------------------------------------------
ParticleEffect.FlowEvents =
{
Inputs =
{
Disable = { ParticleEffect.Event_Disable, "bool" },
Enable = { ParticleEffect.Event_Enable, "bool" },
Restart = { ParticleEffect.Event_Restart, "bool" },
Spawn = { ParticleEffect.Event_Spawn, "bool" },
Kill = { ParticleEffect.Event_Kill, "bool" },
},
Outputs =
{
Disable = "bool",
Enable = "bool",
Restart = "bool",
Spawn = "bool",
},
}
-------------------------------------------------------
-- client functions
-------------------------------------------------------
-------------------------------------------------------
function ParticleEffect.Client:OnInit()
self:SetRegisterInSectors(1);
self.Properties.ParticleEffect = self:PreLoadParticleEffect( self.Properties.ParticleEffect );
self:SetUpdatePolicy(ENTITY_UPDATE_POT_VISIBLE);
--self:SetFlags(ENTITY_FLAG_CLIENT_ONLY, 0);
if (self.Properties.bActive ~= 0) then
self:GotoState( "Active" );
else
self:GotoState( "Idle" );
end
--self:NetPresent(nil);
end
-------------------------------------------------------
function ParticleEffect.Client:ClEvent_Spawn()
if( not CryAction.IsServer() ) then
self:Event_Spawn();
end
end
-------------------------------------------------------
function ParticleEffect.Client:ClEvent_Enable()
if( not CryAction.IsServer() ) then
self:Event_Enable();
end
end
-------------------------------------------------------
function ParticleEffect.Client:ClEvent_Disable()
if( not CryAction.IsServer() ) then
self:Event_Disable();
end
end
-------------------------------------------------------
function ParticleEffect.Client:ClEvent_Restart()
if( not CryAction.IsServer() ) then
self:Event_Restart();
end
end
-------------------------------------------------------
function ParticleEffect.Client:ClEvent_Kill()
if( not CryAction.IsServer() ) then
self:Event_Kill();
end
end
@@ -0,0 +1,669 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
Script.ReloadScript( "Scripts/Entities/Physics/BasicEntity.lua" );
SEQUENCE_NOT_STARTED = 0;
SEQUENCE_PLAYING = 1;
SEQUENCE_STOPPED = 2;
AnimObject =
{
Properties =
{
Animation =
{
Animation = "Default",
Speed = 1,
bLoop = 1,
bPlaying = 1,
bAlwaysUpdate = 0,
playerAnimationState = "",
bPhysicalizeAfterAnimation = 0,
},
Physics =
{
bArticulated = 0,
bRigidBody = 0,
bPushableByPlayers = 0,
bBulletCollisionEnabled = 1,
},
Rendering =
{
bWrinkleMap = 0,
},
Cinematic =
{
bOnDemandModelLoad = 0,
bRenderAlways = 0,
},
ActivatePhysicsThreshold = 0,
ActivatePhysicsDist = 50,
bNoFriendlyFire = 0,
object_Model = "",
MultiplayerOptions =
{
bNetworked = 0,
},
},
PHYSICALIZEAFTER_TIMER = 1,
POSTQL_TIMER = 2,
Client = {},
Server = {},
Editor =
{
Icon = "animobject.bmp",
IconOnTop = 0,
}
};
Net.Expose
{
Class = AnimObject,
ClientMethods =
{
ClEvent_StartAnimation = { RELIABLE_ORDERED, NO_ATTACH, FLOAT, },
ClEvent_ResetAnimation = { RELIABLE_ORDERED, NO_ATTACH, },
ClSync = { RELIABLE_ORDERED, NO_ATTACH, FLOAT, FLOAT, FLOAT, },
},
ServerMethods =
{
SVSync = { RELIABLE_ORDERED, NO_ATTACH, },
},
ServerProperties = {},
};
MakeDerivedEntityOverride( AnimObject,BasicEntity )
function AnimObject:LoadModelOnDemand()
return self.Properties.Cinematic.bOnDemandModelLoad;
end
------------------------------------------------------------------------------------------------------
function AnimObject:SetFromProperties()
self.controllingAnimHere = true;
self.isModelLoaded = false;
self.isRagdollized = false;
self.__super.SetFromProperties(self); -- Call parent function.
self.touchedByFlownode = false;
self.animstarted = 0;
self.sequenceStatus = SEQUENCE_NOT_STARTED;
local Properties = self.Properties;
-- if (Properties.Animation.bPlaying ~= self.bAnimPlaying or Properties.Animation.bLoop ~= self.bAnimLoop or
-- Properties.Animation.Animation ~= self.animName or Properties.Animation.Speed ~= self.animationSpeed) then
self.bAnimPlaying = Properties.Animation.bPlaying;
self.bAnimLoop = Properties.Animation.bLoop;
self.animName = Properties.Animation.Animation;
if (Properties.Animation.bPlaying == 1) then
self:DoStartAnimation();
else
self:ResetAnimation(0, -1);
end
-- end
if (Properties.Animation.bAlwaysUpdate == 1) then
self:Activate(1);
end
self:SetAnimationSpeed( 0, 0, Properties.Animation.Speed )
self.animationSpeed = Properties.Animation.Speed;
self.curAnimTime = 0;
if (self.Properties.ActivatePhysicsThreshold>0) then
local apd = { threshold = self.Properties.ActivatePhysicsThreshold, detach_distance = self.Properties.ActivatePhysicsDist }
self:SetPhysicParams(PHYSICPARAM_AUTO_DETACHMENT, apd);
end
self:CheckShaderParamCallbacks();
end
------------------------------------------------------------------------------------------------------
function AnimObject:SetupModel()
if (self:LoadModelOnDemand()==0 or System.IsEditor()) then
self:LoadAndPhysicalizeModel();
else
Game.CacheResource("AnimObject.lua", self.Properties.object_Model, eGameCacheResourceType_StaticObject, 0);
end
end
-------------------------------------------------------------------------------------------------------
function AnimObject:LoadAndPhysicalizeModel()
if (not self.isModelLoaded) then
self:LoadObject(0,self.Properties.object_Model);
self:RenderAlways(self.Properties.Cinematic.bRenderAlways);
if (self.Properties.Physics.bPhysicalize == 1) then
self:PhysicalizeThis();
end
self.isModelLoaded = true;
return 1;
end
return 0;
end
-------------------------------------------------------------------------------------------------------
function AnimObject:UnloadModel()
if (self.isModelLoaded) then
self:DestroyPhysics();
self:FreeSlot(0);
self.isModelLoaded = false;
end
end
------------------------------------------------------------------------------------------------------
function AnimObject:OnSpawn()
if (self.Properties.MultiplayerOptions.bNetworked == 0) then
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
self.isRagdollized = false;
self.__super.OnSpawn(self); -- Call parent
if (self.Properties.Animation.bAlwaysUpdate == 1) then
CryAction.CreateGameObjectForEntity(self.id);
CryAction.BindGameObjectToNetwork(self.id);
CryAction.ForceGameObjectUpdate(self.id, true);
self:Activate(1);
end
end
------------------------------------------------------------------------------------------------------
function AnimObject:OnReset()
self.__super.OnReset(self); -- Call parent
self.bAnimPlaying = 0;
self:SetFromProperties();
self.sequenceStatus = SEQUENCE_NOT_STARTED;
end
------------------------------------------------------------------------------------------------------
function AnimObject:Event_ResetAnimation()
self.controllingAnimHere = true;
self:ResetAnimation(0, -1);
self.animstarted=0;
--
local PhysProps = self.Properties.Physics;
if( PhysProps.Mass>0 ) then
self:OnReset();
else
self.animName = self.Properties.Animation.Animation;
self:StartAnimation( 0,self.Properties.Animation.Animation,0,0,0,false );
end;
-- net
if( CryAction.IsServer() and self.allClients ) then
self.allClients:ClEvent_ResetAnimation();
end
end
------------------------------------------------------------------------------------------------------
function AnimObject:Event_StartAnimation(sender)
self.controllingAnimHere = true;
self:StartEntityAnimation();
self.animstarted=1;
if( CryAction.IsServer() and self.allClients) then
self.allClients:ClEvent_StartAnimation(CryAction.GetServerTime());
--Log("Server:ClEvent_StartAnimation call"..self:GetName());
end
end
------------------------------------------------------------------------------------------------------
function AnimObject:Event_StopAnimation(sender)
self.controllingAnimHere = true;
if (self.animstarted == 1 and self:IsAnimationRunning(0,0)) then
self.curAnimTime = self:GetAnimationTime(0,0);
else
self.curAnimTime = 0;
end
self:StopAnimation(0, -1); -- all layers
self.animstarted = 0;
end
------------------------------------------------------------------------------------------------------
function AnimObject:Event_RagdollizeDerived()
self.isRagdollized = true;
end
------------------------------------------------------------------------------------------------------
function AnimObject:Event_ModelLoad()
local justLoaded = self:LoadAndPhysicalizeModel();
if(justLoaded ~= 0) then
self:RelinkAllEntities();
end
end
------------------------------------------------------------------------------------------------------
function AnimObject:Event_ModelUnload()
if (not System.IsEditor()) then
self:UnloadModel();
end
end
------------------------------------------------------------------------------------------------------
function AnimObject:Event_RenderAlwaysEnable()
self:RenderAlways(1);
end
------------------------------------------------------------------------------------------------------
function AnimObject:Event_RenderAlwaysDisable()
self:RenderAlways(0);
end
------------------------------------------------------------------------------------------------------
function AnimObject:DoStartAnimation()
self.animName = self.Properties.Animation.Animation;
self:StartAnimation( 0,self.Properties.Animation.Animation,0,0,self.Properties.Animation.Speed,self.Properties.Animation.bLoop,1 );
self:ForceCharacterUpdate(0, true);
self.animstarted = 1;
-- save curAnimTime for QS/QL
if (self.Properties.Animation.Speed < 0) then
self.curAnimTime = 0;
else
self.curAnimTime = self:GetAnimationLength(0, self.Properties.Animation.Animation);
end
-- local currTime = System.GetCurrTime();
self.startTime = CryAction.GetServerTime();--System.GetCurrAsyncTime();
if( self.timeDiff ) then
self.startTime=self.startTime-self.timeDiff;
end
end
------------------------------------------------------------------------------------------------------
function AnimObject:StartEntityAnimation()
self:StopAnimation(0, -1);
self:DoStartAnimation();
self.bStopAnimAfterQL = false;
self:KillTimer(self.POSTQL_TIMER);
local playerAnimationState = self.Properties.Animation.playerAnimationState;
if (g_localActor and playerAnimationState ~= "") then
g_localActor.actor:CreateCodeEvent(
{
event = "animationControl",pos=self:GetWorldPos(),angle=self:GetWorldAngles()
}
); --,entId=self.id})
g_localActor.actor:QueueAnimationState(playerAnimationState);
if (self.Properties.Animation.bPhysicalizeAfterAnimation == 1) then
local animLen = self:GetAnimationLength(0,self.Properties.Animation.Animation) * 1000.0 / self.Properties.Animation.Speed;
self:SetTimer(self.PHYSICALIZEAFTER_TIMER,animLen);
--Log("timer set to:"..animLen.."ms");
end
end
end
------------------------------------------------------------------------------------------------------
function AnimObject.Client:OnTimer(timerId,mSec)
if (timerId == self.PHYSICALIZEAFTER_TIMER) then
local PhysProps = self.Properties.Physics;
PhysProps.bRigidBodyActive = 1;
PhysProps.bPhysicalize=1;
PhysProps.bRigidBody=1;
PhysProps.bResting = 0;
if (self.bRigidBodyActive ~= PhysProps.bRigidBodyActive) then
self.bRigidBodyActive = PhysProps.bRigidBodyActive;
self:PhysicalizeThis();
end
if (PhysProps.bRigidBody == 1) then
self:AwakePhysics(1-PhysProps.bResting);
self.bRigidBodyActive = PhysProps.bRigidBodyActive;
end
end
if (timerId == self.POSTQL_TIMER and self.sequenceStatus == SEQUENCE_NOT_STARTED) then
self:StopAnimation(0, -1);
end
end
------------------------------------------------------------------------------------------------------
function AnimObject:CorrectTiming(frameTime)
-- local skip = 0;
-- if( skip==0 ) then
if( self.animstarted==1 and self:IsAnimationRunning(0,0) and self.Properties.Animation.Speed>0 ) then
local curTime = CryAction.GetServerTime();--System.GetCurrAsyncTime();
local diffRealTime = (curTime-self.startTime)*self.Properties.Animation.Speed;
local curAnimTime = self:GetAnimationTime(0,0);
if( curAnimTime<=self.curAnimTime ) then
local diff = diffRealTime-curAnimTime;
if( diff<-0.02 ) then
-- correct speed
local frameTimeAnim = self.Properties.Animation.Speed*frameTime;
local reqTime = frameTimeAnim-diff;
local ratio = (frameTimeAnim)/reqTime;
if( ratio<0.5 ) then
-- clamp
ratio=0.5;
end
--
newSpeed = ratio*self.Properties.Animation.Speed;
self:SetAnimationSpeed( 0, 0, newSpeed );
--System.LogToConsole(self:GetName().." RealLess="..diff.." Speed="..newSpeed);
else
if( diff>0.02 ) then
-- correct speed
local frameTimeAnim = self.Properties.Animation.Speed*frameTime;
local reqTime = frameTimeAnim+diff;
local ratio = reqTime/(frameTimeAnim);
if( ratio>1.1 ) then
-- clamp
ratio=1.1;
end
newSpeed = ratio*self.Properties.Animation.Speed;
self:SetAnimationSpeed( 0, 0, newSpeed );
--System.LogToConsole(self:GetName().." RealMore="..diff.." Speed="..newSpeed);
else
-- restore speed
if( self.Properties.Animation.Speed>0 ) then
self:SetAnimationSpeed( 0, 0, self.Properties.Animation.Speed );
end
end
end
end
end
-- end
end
------------------------------------------------------------------------------------------------------
function AnimObject.Server:OnUpdate(dt)
if( CryAction.IsServer() ) then
self:CorrectTiming(dt);
end
end
------------------------------------------------------------------------------------------------------
function AnimObject.Client:OnUpdate(dt)
if( CryAction.IsClient() and not CryAction.IsServer() ) then
self:CorrectTiming(dt);
end
if (self.bStopAnimAfterQL) then
self.bStopAnimAfterQL = false;
self:SetTimer(self.POSTQL_TIMER, 0.2);
if (self.Properties.Animation.bAlwaysUpdate ~= 1) then
self:Activate(0);
end
end
end
-------------------------------------------------------
function AnimObject:OnLoad(table)
local wasRagollized = table.isRagdollized;
if (self.isRagdollized and (not wasRagdollized)) then -- for now we dont care about the oposite situation: the object was ragdollized before the save, and is not ragdollized now.
self:OnReset();
end
--self.__super.OnLoad( self,table ); -- Call parent
self.bAnimPlaying = table.bAnimPlaying;
self.bAnimLoop = table.bAnimLoop;
self.animName = table.animName;
self.animstarted = table.animstarted;
self.health = table.health;
self.dead = table.dead;
self.controllingAnimHere = table.bControllingAnimHere;
-- self.movedByFlowgraph = table.movedByFlowgraph;
if (self.controllingAnimHere) then
if (self.animstarted == 1) then -- restart animation
self:StartEntityAnimation();
self:SetAnimationTime(0, 0, table.animTime);
else
--we have to stop the animation
-- either at the point stored in the file
if (table.animTime > 0) then
if (self.animName~=self.Properties.Animation.Animation) then
self:StartAnimation( 0, self.animName, 0, 0, self.Properties.Animation.Speed,self.Properties.Animation.bLoop,1 );
self:SetAnimationTime(0, 0, table.animTime);
else
self:StartEntityAnimation();
end
self:SetAnimationSpeed( 0, 0, 0.0 );
self:SetAnimationTime(0, 0, table.animTime);
self.bStopAnimAfterQL = true;
self:Activate(1);
self.curAnimTime = table.animTime;
end
if (table.animTime==0) then
local bTouchedByTrackview = (table.sequenceStatus == SEQUENCE_NOT_STARTED and self.sequenceStatus ~= SEQUENCE_NOT_STARTED);
-- this check makes no sense imo. But im not removing it at this time (c3 last weeks) to avoid any risk
if (bTouchedByTrackview or self.touchedByFlownode) then
-- or just at the beginning
self:ResetAnimation(0, -1);
self:StartEntityAnimation();
self:SetAnimationSpeed(0, 0, 0.0);
self:SetAnimationTime(0, 0, 0.0);
self.bStopAnimAfterQL = true;
self:Activate(1);
self.curAnimTime = 0;
end
end
end
else
self.externalAnim_anim = table.externalAnim_anim;
self.externalAnim_layer = table.externalAnim_layer;
self.externalAnim_loop = table.externalAnim_loop;
self:StartAnimation( 0, self.externalAnim_anim, self.externalAnim_layer, 0, 1, self.externalAnim_loop );
self:SetAnimationTime(0, self.externalAnim_layer, table.animTime);
end
self.touchedByFlownode = false;
-- physicalized ones that are neither articulated neither rigidbody become static. Static physical entities are not serialized at all. So we just rephysicallize in that case.
if (self.Properties.Physics.bArticulated==0 and self.Properties.Physics.bRigidBody==0 and self.Properties.Physics.bPhysicalize==1) then
self:PhysicalizeThis();
end
self.sequenceStatus = table.sequenceStatus;
end
-------------------------------------------------------
function AnimObject:OnSave(table)
table.isRagdollized = self.isRagdollized;
table.bAnimPlaying = self.bAnimPlaying
table.bAnimLoop = self.bAnimLoop
table.animName = self.animName
table.sequenceStatus = self.sequenceStatus;
table.health = self.health;
table.dead = self.dead;
table.bControllingAnimHere = self.controllingAnimHere;
if (self.controllingAnimHere) then
if (self.animstarted == 1 and self:IsAnimationRunning(0,0)) then
table.animTime = self:GetAnimationTime(0,0);
table.animstarted = 1;
else
table.animstarted = 0;
if (self.curAnimTime) then
table.animTime = self.curAnimTime;
else
table.animTime = 0;
end
end
else
table.externalAnim_anim = self.externalAnim_anim;
table.externalAnim_layer = self.externalAnim_layer;
table.externalAnim_loop = self.externalAnim_loop;
table.animTime = self:GetAnimationTime(0,self.externalAnim_layer);
end
end
------------------------------------------------------------------------------------------------------
-- Additional Flow events.
------------------------------------------------------------------------------------------------------
AnimObject.FlowEvents.Inputs.ResetAnimation = { AnimObject.Event_ResetAnimation, "bool" }
AnimObject.FlowEvents.Inputs.StartAnimation = { AnimObject.Event_StartAnimation, "bool" }
AnimObject.FlowEvents.Inputs.StopAnimation = { AnimObject.Event_StopAnimation, "bool" }
AnimObject.FlowEvents.Inputs.ModelLoad = { AnimObject.Event_ModelLoad, "bool" }
AnimObject.FlowEvents.Inputs.ModelUnload = { AnimObject.Event_ModelUnload, "bool" }
-- client functions
function AnimObject.Client:ClEvent_StartAnimation(servertime)
--Log("ClEvent_StartAnimation recieved"..self:GetName());
self.timeDiff = CryAction.GetServerTime()-servertime;
-- local localDiff = System.GetCurrTime()-servertime;
-- if( self.timeDiff>0.1 ) then
-- System.LogToConsole(self:GetName().." Diff="..self.timeDiff.." localDiff="..localDiff);
-- else
-- if( self.timeDiff<-0.1 ) then
-- System.LogToConsole(self:GetName().." Diff="..self.timeDiff);
-- end
-- end
if( not CryAction.IsServer() ) then
self:Event_StartAnimation();
end
end
function AnimObject.Client:ClEvent_ResetAnimation()
if( not CryAction.IsServer() ) then
self:Event_ResetAnimation();
end
end
------------------------------------------------------------------------------------------------------
function AnimObject:SavePhysicalState()
self.initPos = self:GetPos();
self.initRot = self:GetWorldAngles();
self.initScale = self:GetScale();
end
function AnimObject:RestorePhysicalState()
self:SetPos(self.initPos);
self:SetWorldAngles(self.initRot);
self:SetScale(self.initScale);
-- restore
self:ResetAnimation(0, -1);
self.animstarted=0;
local PhysProps = self.Properties.Physics;
if( PhysProps.Mass>0 ) then
self:OnReset();
else
self.animName = self.Properties.Animation.Animation;
self:StartAnimation( 0,self.Properties.Animation.Animation,0,0,0,false );
end;
end
------------------------------------------------------------------------------------------------------
function AnimObject:PhysicalizeThis()
BasicEntity.PhysicalizeThis(self);
-- Remove bullet collision if desired
local Physics = self.Properties.Physics;
if (Physics.bBulletCollisionEnabled == 0) then
local flagstab = { flags_mask= geom_colltype_ray + geom_colltype_foliage_proxy, flags=geom_colltype_player*Physics.bPushableByPlayers };
self:SetPhysicParams(PHYSICPARAM_PART_FLAGS, flagstab);
end
end
------------------------------------------------------------------------------------------------------
function AnimObject:SendSyncToClient( channelId )
if( self.animstarted==1 ) then
animTime = self:GetAnimationTime(0,0);
self.onClient:ClSync( channelId, animTime, self.startTime, CryAction.GetServerTime() )
end
end
function AnimObject.Server:OnPostInitClient( channelId )
self:SendSyncToClient(channelId);
end
function AnimObject.Server:SVSync(channelId)
self:SendSyncToClient(channelId);
end
function AnimObject.Client:ClSync( animTimeValue, startTimeValue, serverTimeValue )
-- if( self.animstarted==0 ) then
--self:Event_ResetAnimation();
--self.timeDiff = CryAction.GetServerTime()-serverTimeValue;
self:StartEntityAnimation();
self.startTime = startTimeValue;
self:SetAnimationTime(0,0,animTimeValue);
--Log("CLSync recieved"..self:GetName()..animTimeValue);
-- end
end
function AnimObject:UpdateFromServer()
self.server:SVSync();
end
-- notifications from PlaySequence FG node (entire sequence starts/stops)
function AnimObject:OnSequenceStart()
self.sequenceStatus = SEQUENCE_PLAYING;
end
function AnimObject:OnSequenceStop()
self.sequenceStatus = SEQUENCE_STOPPED;
end
-- Notifications from trackview (animation in sequence starts/stops)
function AnimObject:OnSequenceAnimationStart( animName )
self.sequenceStatus = SEQUENCE_PLAYING;
self.animName = animName;
end
function AnimObject:OnSequenceAnimationStop()
self.sequenceStatus = SEQUENCE_STOPPED;
end
function AnimObject:OnFlowGraphAnimationStart( animName, layer, loop )
self.animName = animName;
self.externalAnim_anim = animName;
self.controllingAnimHere = false;
self.externalAnim_layer = layer;
self.externalAnim_loop = loop;
self.touchedByFlownode = true;
end
function AnimObject:OnFlowGraphAnimationStop()
if (self.externalAnim_layer) then
self.curAnimTime = self:GetAnimationTime(0, self.externalAnim_layer);
end
self.controllingAnimHere = true;
end
function AnimObject:OnFlowGraphAnimationEnd()
self.curAnimTime = 1; -- is a normalized time, so 1 == end
self.controllingAnimHere = true;
end
@@ -0,0 +1,99 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
AreaBezierVolume = {
type = "AreaBezierVolume",
Properties =
{
bEnabled = 1,
MultiplayerOptions = {
bNetworked = 0,
},
},
}
-------------------------------------------------------------------------------------------------------
function AreaBezierVolume:OnSpawn()
if (self.Properties.MultiplayerOptions.bNetworked == 0) then
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
end
-------------------------------------------------------
function AreaBezierVolume:OnLoad(table)
self.bEnabled = table.bEnabled
if(self.bEnabled == 1) then
self:Event_Enable();
else
self:Event_Disable();
end
end
-------------------------------------------------------
function AreaBezierVolume:OnSave(table)
table.bEnabled = self.bEnabled
end
-------------------------------------------------------
function AreaBezierVolume:OnInit()
if(self.Properties.bEnabled == 1) then
self:Event_Enable();
else
self:Event_Disable();
end
end
function AreaBezierVolume:OnPropertyChange()
if(self.Properties.bEnabled == 1) then
self:Event_Enable();
else
self:Event_Disable();
end
end
-------------------------------------------------------
function AreaBezierVolume:OnEnable(enable)
--Log("AreaBezierVolume:OnEnable");
self:SetPhysicParams(PHYSICPARAM_FOREIGNDATA,{foreignData = ZEROG_AREA_ID});
end
-------------------------------------------------------
function AreaBezierVolume:Event_Enable()
--self:TriggerEvent(AIEVENT_ENABLE);
self.bEnabled = 1;
BroadcastEvent(self, "Enable");
end
-------------------------------------------------------
function AreaBezierVolume:Event_Disable()
--self:TriggerEvent(AIEVENT_DISABLE);
self.bEnabled = 0;
BroadcastEvent(self, "Disable");
end
AreaBezierVolume.FlowEvents =
{
Inputs =
{
Disable = { AreaBezierVolume.Event_Disable, "bool" },
Enable = { AreaBezierVolume.Event_Enable, "bool" },
},
Outputs =
{
Disable = "bool",
Enable = "bool",
},
}
@@ -0,0 +1,269 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
Script.ReloadScript("scripts/Utils/EntityUtils.lua")
-- Basic entity
BasicEntity = {
Properties = {
soclasses_SmartObjectClass = "",
--bAutoGenAIHidePts = 0,
bMissionCritical = 0,
bCanTriggerAreas = 0,
DmgFactorWhenCollidingAI = 1,
object_Model = "objects/default/primitive_sphere.cgf",
Physics = {
bPhysicalize = 1, -- True if object should be physicalized at all.
bRigidBody = 1, -- True if rigid body, False if static.
bPushableByPlayers = 1,
Density = -1,
Mass = -1,
},
MultiplayerOptions = {
bNetworked = 0,
},
bExcludeCover=0,
},
Client = {},
Server = {},
-- Temp.
_Flags = {},
Editor={
Icon = "physicsobject.bmp",
IconOnTop=1,
},
}
local Physics_DX9MP_Simple = {
bPhysicalize = 1, -- True if object should be physicalized at all.
bPushableByPlayers = 0,
Density = 0,
Mass = 0,
}
------------------------------------------------------------------------------------------------------
function BasicEntity:OnSpawn()
if (self.Properties.MultiplayerOptions.bNetworked == 0) then
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
self.bRigidBodyActive = 1;
self:SetFromProperties();
end
------------------------------------------------------------------------------------------------------
function BasicEntity:SetFromProperties()
local Properties = self.Properties;
if (Properties.object_Model == "") then
do return end;
end
self.freezable = (tonumber(Properties.bFreezable) ~= 0);
self:SetupModel();
-- Mark AI hideable flag.
if (Properties.bAutoGenAIHidePts == 1) then
self:SetFlags(ENTITY_FLAG_AI_HIDEABLE, 0); -- set
else
self:SetFlags(ENTITY_FLAG_AI_HIDEABLE, 2); -- remove
end
if (self.Properties.bCanTriggerAreas == 1) then
self:SetFlags(ENTITY_FLAG_TRIGGER_AREAS, 0); -- set
else
self:SetFlags(ENTITY_FLAG_TRIGGER_AREAS, 2); -- remove
end
end
------------------------------------------------------------------------------------------------------
function BasicEntity:SetupModel()
local Properties = self.Properties;
self:LoadObject(0,Properties.object_Model);
if (Properties.Physics.bPhysicalize == 1) then
self:PhysicalizeThis();
end
end
------------------------------------------------------------------------------------------------------
function BasicEntity:OnLoad(table)
self.health = table.health;
self.dead = table.dead;
end
function BasicEntity:OnSave(table)
table.health = self.health;
table.dead = self.dead;
end
------------------------------------------------------------------------------------------------------
function BasicEntity:IsRigidBody()
local Properties = self.Properties;
local Mass = Properties.Mass;
local Density = Properties.Density;
if (Mass == 0 or Density == 0 or Properties.bPhysicalize ~= 1) then
return false;
end
return true;
end
------------------------------------------------------------------------------------------------------
function BasicEntity:PhysicalizeThis()
-- Init physics.
local Physics = self.Properties.Physics;
if (CryAction.IsImmersivenessEnabled() == 0) then
Physics = Physics_DX9MP_Simple;
end
EntityCommon.PhysicalizeRigid( self,0,Physics,self.bRigidBodyActive );
end
------------------------------------------------------------------------------------------------------
-- OnPropertyChange called only by the editor.
------------------------------------------------------------------------------------------------------
function BasicEntity:OnPropertyChange()
-- if the properties are changed, we force a reset in the __usable
if (self.__usable) then
if (self.__origUsable ~= self.Properties.bUsable or self.__origPickable ~= self.Properties.bPickable) then
self.__usable = nil;
end
end
self:SetFromProperties();
end
------------------------------------------------------------------------------------------------------
-- OnReset called only by the editor.
------------------------------------------------------------------------------------------------------
function BasicEntity:OnReset()
self:ResetOnUsed()
local PhysProps = self.Properties.Physics;
if (PhysProps.bPhysicalize == 1) then
self:PhysicalizeThis();
self:AwakePhysics(0);
end
end
------------------------------------------------------------------------------------------------------
function BasicEntity:Event_Remove()
self:DrawSlot(0,0);
self:DestroyPhysics();
self:ActivateOutput( "Remove", true );
end
------------------------------------------------------------------------------------------------------
function BasicEntity:Event_Hide()
self:Hide(1);
self:ActivateOutput( "Hide", true );
if CurrentCinematicName then
Log("%.3f %s %s : Event_Hide", _time, CurrentCinematicName, self:GetName() );
end
end
------------------------------------------------------------------------------------------------------
function BasicEntity:Event_UnHide()
self:Hide(0);
self:ActivateOutput( "UnHide", true );
if CurrentCinematicName then
Log("%.3f %s %s : Event_UnHide", _time, CurrentCinematicName, self:GetName() );
end
end
------------------------------------------------------------------------------------------------------
function BasicEntity:Event_Ragdollize()
self:RagDollize(0);
self:ActivateOutput( "Ragdollized", true );
if (self.Event_RagdollizeDerived) then
self:Event_RagdollizeDerived();
end
end
------------------------------------------------------------------------------------------------------
function BasicEntity.Client:OnPhysicsBreak( vPos,nPartId,nOtherPartId )
self:ActivateOutput("Break",nPartId+1 );
end
function BasicEntity:IsUsable(user)
local ret = nil
-- From EntityUtils.lua
if not self.__usable then self.__usable = self.Properties.bUsable end
local mp = System.IsMultiplayer();
if(mp and mp~=0) then
return 0;
end
if (self.__usable == 1) then
ret = 2
else
local PhysProps = self.Properties.Physics;
if (self:IsRigidBody() == true and user and user.CanGrabObject) then
ret = user:CanGrabObject(self)
end
end
return ret or 0
end
BasicEntity.FlowEvents =
{
Inputs =
{
Used = { BasicEntity.Event_Used, "bool" },
EnableUsable = { BasicEntity.Event_EnableUsable, "bool" },
DisableUsable = { BasicEntity.Event_DisableUsable, "bool" },
Hide = { BasicEntity.Event_Hide, "bool" },
UnHide = { BasicEntity.Event_UnHide, "bool" },
Remove = { BasicEntity.Event_Remove, "bool" },
Ragdollize = { BasicEntity.Event_Ragdollize, "bool" },
},
Outputs =
{
Used = "bool",
EnableUsable = "bool",
DisableUsable = "bool",
Activate = "bool",
Hide = "bool",
UnHide = "bool",
Remove = "bool",
Ragdollized = "bool",
Break = "int",
},
}
MakeUsable(BasicEntity);
MakePickable(BasicEntity);
MakeTargetableByAI(BasicEntity);
MakeKillable(BasicEntity);
AddHeavyObjectProperty(BasicEntity);
AddInteractLargeObjectProperty(BasicEntity);
SetupCollisionFiltering(BasicEntity);
@@ -0,0 +1,276 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
Script.ReloadScript("scripts/Utils/EntityUtils.lua")
-- Basic entity
LivingEntity = {
Properties = {
soclasses_SmartObjectClass = "",
bMissionCritical = 0,
bCanTriggerAreas = 1,
DmgFactorWhenCollidingAI = 1,
object_Model = "objects/default/primitive_capsule.cgf",
Physics = {
bPhysicalize = 1, -- True if object should be physicalized at all.
bPushableByPlayers = 1,
},
Living = {
height = 0, -- vertical offset of collision geometry center
vector_size = {0.4, 0.4,0.9}, -- collision cylinder dimensions
height_eye = 1.8, -- vertical offset of camera
height_pivot = 0.1, -- offset from central ground position that is considered entity center
head_radius = 0.3, -- radius of the 'head' geometry (used for camera offset)
height_head = 1.7, -- center.z of the head geometry
groundContactEps = 0.004, --the amount that the living needs to move upwards before ground contact is lost. defaults to which ever is greater 0.004, or 0.01*geometryHeight
bUseCapsule = 1,--switches between capsule and cylinder collider geometry
inertia = 1, -- inertia koefficient, the more it is, the less inertia is, 0 means no inertia
inertiaAccel = 1, -- inertia on acceleration
air_control = 1, -- air control koefficient 0..1, 1 - special value (total control of movement)
air_resistance = 0.1, -- standard air resistance
gravity = 9.8, -- gravity vector
mass = 100, -- mass (in kg)
min_slide_angle = 60, -- if surface slope is more than this angle, player starts sliding (angle is in radians)
max_climb_angle = 60, -- player cannot climb surface which slope is steeper than this angle
max_jump_angle = 45, -- player is not allowed to jump towards ground if this angle is exceeded
min_fall_angle = 65, -- player starts falling when slope is steeper than this
max_vel_ground = 10, -- player cannot stand of surfaces that are moving faster than this
timeImpulseRecover = 0.3, -- forcefully turns on inertia for that duration after receiving an impulse
nod_speed = 1, -- vertical camera shake speed after landings
bActive = 1,-- 0 disables all simulation for the character, apart from moving along the requested velocity
collision_types = 271, -- (271 = ent_static | ent_terrain | ent_living | ent_rigid | ent_sleeping_rigid) entity types to check collisions against
},
MultiplayerOptions = {
bNetworked = 0,
},
bExcludeCover=0,
},
Client = {},
Server = {},
-- Temp.
_Flags = {},
Editor={
Icon = "physicsobject.bmp",
IconOnTop=1,
},
}
------------------------------------------------------------------------------------------------------
function LivingEntity:OnSpawn()
if (self.Properties.MultiplayerOptions.bNetworked == 0) then
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
self:SetFromProperties();
end
------------------------------------------------------------------------------------------------------
function LivingEntity:SetFromProperties()
local Properties = self.Properties;
if (Properties.object_Model == "") then
do return end;
end
self.freezable = (tonumber(Properties.bFreezable) ~= 0);
self:SetupModel();
-- Mark AI hideable flag.
if (Properties.bAutoGenAIHidePts == 1) then
self:SetFlags(ENTITY_FLAG_AI_HIDEABLE, 0); -- set
else
self:SetFlags(ENTITY_FLAG_AI_HIDEABLE, 2); -- remove
end
if (self.Properties.bCanTriggerAreas == 1) then
self:SetFlags(ENTITY_FLAG_TRIGGER_AREAS, 0); -- set
else
self:SetFlags(ENTITY_FLAG_TRIGGER_AREAS, 2); -- remove
end
end
------------------------------------------------------------------------------------------------------
function LivingEntity:SetupModel()
local Properties = self.Properties;
self:LoadObject(0,Properties.object_Model);
if (Properties.Physics.bPhysicalize == 1) then
self:PhysicalizeThis();
end
end
------------------------------------------------------------------------------------------------------
function LivingEntity:OnLoad(table)
self.health = table.health;
self.dead = table.dead;
end
function LivingEntity:OnSave(table)
table.health = self.health;
table.dead = self.dead;
end
------------------------------------------------------------------------------------------------------
function LivingEntity:IsRigidBody()
local Properties = self.Properties;
local Mass = Properties.Mass;
local Density = Properties.Density;
if (Mass == 0 or Density == 0 or Properties.bPhysicalize ~= 1) then
return false;
end
return true;
end
------------------------------------------------------------------------------------------------------
function LivingEntity:PhysicalizeThis()
Entity.Physicalize(self,0, PE_LIVING, self.Properties);
end
------------------------------------------------------------------------------------------------------
-- OnPropertyChange called only by the editor.
------------------------------------------------------------------------------------------------------
function LivingEntity:OnPropertyChange()
-- if the properties are changed, we force a reset in the __usable
if (self.__usable) then
if (self.__origUsable ~= self.Properties.bUsable or self.__origPickable ~= self.Properties.bPickable) then
self.__usable = nil;
end
end
self:SetFromProperties();
end
------------------------------------------------------------------------------------------------------
-- OnReset called only by the editor.
------------------------------------------------------------------------------------------------------
function LivingEntity:OnReset()
self:ResetOnUsed()
local PhysProps = self.Properties.Physics;
if (PhysProps.bPhysicalize == 1) then
self:PhysicalizeThis();
self:AwakePhysics(0);
end
end
------------------------------------------------------------------------------------------------------
function LivingEntity:Event_Remove()
self:DrawSlot(0,0);
self:DestroyPhysics();
self:ActivateOutput( "Remove", true );
end
------------------------------------------------------------------------------------------------------
function LivingEntity:Event_Hide()
self:Hide(1);
self:ActivateOutput( "Hide", true );
if CurrentCinematicName then
Log("%.3f %s %s : Event_Hide", _time, CurrentCinematicName, self:GetName() );
end
end
------------------------------------------------------------------------------------------------------
function LivingEntity:Event_UnHide()
self:Hide(0);
self:ActivateOutput( "UnHide", true );
if CurrentCinematicName then
Log("%.3f %s %s : Event_UnHide", _time, CurrentCinematicName, self:GetName() );
end
end
------------------------------------------------------------------------------------------------------
function LivingEntity:Event_Ragdollize()
self:RagDollize(0);
self:ActivateOutput( "Ragdollized", true );
if (self.Event_RagdollizeDerived) then
self:Event_RagdollizeDerived();
end
end
------------------------------------------------------------------------------------------------------
function LivingEntity.Client:OnPhysicsBreak( vPos,nPartId,nOtherPartId )
self:ActivateOutput("Break",nPartId+1 );
end
function LivingEntity:IsUsable(user)
local ret = nil
-- From EntityUtils.lua
if not self.__usable then self.__usable = self.Properties.bUsable end
local mp = System.IsMultiplayer();
if(mp and mp~=0) then
return 0;
end
if (self.__usable == 1) then
ret = 2
else
local PhysProps = self.Properties.Physics;
if (self:IsRigidBody() == true and user and user.CanGrabObject) then
ret = user:CanGrabObject(self)
end
end
return ret or 0
end
LivingEntity.FlowEvents =
{
Inputs =
{
Used = { LivingEntity.Event_Used, "bool" },
EnableUsable = { LivingEntity.Event_EnableUsable, "bool" },
DisableUsable = { LivingEntity.Event_DisableUsable, "bool" },
Hide = { LivingEntity.Event_Hide, "bool" },
UnHide = { LivingEntity.Event_UnHide, "bool" },
Remove = { LivingEntity.Event_Remove, "bool" },
Ragdollize = { LivingEntity.Event_Ragdollize, "bool" },
},
Outputs =
{
Used = "bool",
EnableUsable = "bool",
DisableUsable = "bool",
Activate = "bool",
Hide = "bool",
UnHide = "bool",
Remove = "bool",
Ragdollized = "bool",
Break = "int",
},
}
MakeUsable(LivingEntity);
MakePickable(LivingEntity);
MakeTargetableByAI(LivingEntity);
MakeKillable(LivingEntity);
AddHeavyObjectProperty(LivingEntity);
AddInteractLargeObjectProperty(LivingEntity);
SetupCollisionFiltering(LivingEntity);
@@ -0,0 +1,392 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
Script.ReloadScript( "Scripts/Entities/Physics/BasicEntity.lua" );
-- Basic entity
RigidBodyEx = {
Properties = {
bSerialize = 0, --by default rigid bodies are not being serialized (save/load)
bDamagesPlayerOnCollisionSP = 0,
AI = {
-- This value is currently used for the MNM Navigation System
bUsedAsDynamicObstacle = 1,
},
Physics = {
bRigidBodyActive = 1,
bActivateOnDamage = 0,
bResting = 1, -- If rigid body is originally in resting state.
bCanBreakOthers = 0,
Simulation =
{
max_time_step = 0.02,
sleep_speed = 0.04,
damping = 0,
bFixedDamping = 0,
bUseSimpleSolver = 0,
},
Buoyancy=
{
water_density = 1000,
water_damping = 0,
water_resistance = 1000,
},
CGFPropsOverride =
{
Joint =
{
limit = "",
twist = "",
bend = "",
push = "",
pull = "",
shift = "",
},
Constraint =
{
constraint_limit = "",
constraint_minang = "",
constraint_maxang = "",
constraint_damping = "",
constraint_collides = "",
},
Deformable =
{
stiffness = "",
thickness = "",
max_stretch = "",
max_impulse = "",
skin_dist = "",
hardness = "",
explosion_scale = "",
},
player_can_break = "",
},
ForeignData =
{
bMovingPlatform = 0,
},
},
MultiplayerOptions = {
bNetworked = 0,
},
},
Editor={
Icon = "physicsobject.bmp",
IconOnTop=1,
},
States = {"Default","Activated"},
bRigidBodyActive = 1,
}
local Physics_DX9MP_Simple = {
bRigidBodyActive = 0,
bActivateOnDamage = 0,
bResting = 1, -- If rigid body is originally in resting state.
Simulation =
{
max_time_step = 0.02,
sleep_speed = 0.04,
damping = 0,
bFixedDamping = 0,
bUseSimpleSolver = 0,
},
Buoyancy=
{
water_density = 1000,
water_damping = 0,
water_resistance = 1000,
},
}
MakeDerivedEntity( RigidBodyEx,BasicEntity )
-------------------------------------------------------
function RigidBodyEx:OnLoad(table)
self.bRigidBodyActive = table.bRigidBodyActive;
self.health = table.health;
self.dead = table.dead;
self.broken = table.broken;
end
-------------------------------------------------------
function RigidBodyEx:OnSave(table)
table.bRigidBodyActive = self.bRigidBodyActive
table.health = self.health;
table.dead = self.dead;
table.broken = self.broken;
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:OnSpawn()
if (self.Properties.MultiplayerOptions.bNetworked == 0) then
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
if (self.Properties.Physics.bRigidBodyActive == 1) then
self.bRigidBodyActive = 1;
end
self:SetFromProperties();
self:SetupHealthProperties();
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:SetFromProperties()
local Properties = self.Properties;
if (Properties.object_Model == "") then
do return end;
end
self:LoadObject(0,Properties.object_Model);
self:CharacterUpdateOnRender(0,1); -- If it is a character force it to update on render.
-- Enabling drawing of the slot.
self:DrawSlot(0,1);
self.bRigidBodyActive = Properties.Physics.bRigidBodyActive;
if (Properties.Physics.bPhysicalize == 1) then
self:PhysicalizeThis();
else
local params = {};
self:Physicalize(0,PE_NONE,params);
end
self:GotoState("Default");
-- Mark AI hideable flag.
if (self.Properties.bAutoGenAIHidePts == 1) then
self:SetFlags(ENTITY_FLAG_AI_HIDEABLE, 0); -- set
else
self:SetFlags(ENTITY_FLAG_AI_HIDEABLE, 2); -- remove
end
if (self.Properties.bCanTriggerAreas == 1) then
self:SetFlags(ENTITY_FLAG_TRIGGER_AREAS, 0); -- set
else
self:SetFlags(ENTITY_FLAG_TRIGGER_AREAS, 2); -- remove
end
self.broken = 0;
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:PhysicalizeThis()
-- Init physics.
local physics = self.Properties.Physics;
if (CryAction.IsImmersivenessEnabled() == 0) then
physics = Physics_DX9MP_Simple;
end
EntityCommon.PhysicalizeRigid( self,0,physics,self.bRigidBodyActive );
end
------------------------------------------------------------------------------------------------------
-- OnPropertyChange called only by the editor.
------------------------------------------------------------------------------------------------------
function RigidBodyEx:OnPropertyChange()
self:SetFromProperties();
end
------------------------------------------------------------------------------------------------------
-- OnReset called only by the editor.
------------------------------------------------------------------------------------------------------
function RigidBodyEx:OnReset()
self:ResetOnUsed()
local PhysProps = self.Properties.Physics;
if (PhysProps.bPhysicalize == 1) then
if (self:IsInState("Default") ~= 0) then
self:AwakePhysics(1-self.Properties.Physics.bResting);
end
self:GotoState("Default");
end
self:SetupHealthProperties();
self.broken = 0;
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:Event_Remove()
self:DrawSlot(0,0);
self:DestroyPhysics();
self:ActivateOutput( "Remove", true );
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:Event_Hide()
self:Hide(1);
self:ActivateOutput( "Hide", true );
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:Event_UnHide()
self:Hide(0);
self:ActivateOutput( "UnHide", true );
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:Event_Ragdollize()
self:RagDollize(0);
self:ActivateOutput( "Ragdollized", true );
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:OnPhysicsBreak( vPos,nPartId,nOtherPartId )
self:ActivateOutput("Break",nPartId+1 );
self.broken = 1;
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:OnDamage( hit )
if (self:IsARigidBody() == 1) then
if (self.Properties.Physics.bActivateOnDamage == 1) then
if (hit.explosion and self:GetState()~="Activated") then
BroadcastEvent(self, "Activate");
self:GotoState("AcTivated");
end
end
end
if( hit.ipart and hit.ipart>=0 ) then
self:AddImpulse( hit.ipart, hit.pos, hit.dir, hit.impact_force_mul );
end
end
function RigidBodyEx:IsUsable(user)
local canBeUsed = 0;
if(self.broken == 0) then
if (self.Properties.bUsable==1 or self.Properties.bPickable==1) then
canBeUsed = 1;
end
else
canBeUsed = self.Properties.bUsable;
end
return canBeUsed;
end
------------------------------------------------------------------------------------------------------
-- Input events
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
function RigidBodyEx:Event_Activate(sender)
self:GotoState("Activated");
end
------------------------------------------------------------------------------------------------------
-- Events to switch material Applied to object.
------------------------------------------------------------------------------------------------------
function RigidBodyEx:CommonSwitchToMaterial( numStr )
if (not self.sOriginalMaterial) then
self.sOriginalMaterial = self:GetMaterial();
end
if (self.sOriginalMaterial) then
--System.Log( "Material: "..self.sOriginalMaterial..numStr );
self:SetMaterial( self.sOriginalMaterial..numStr );
end
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:Event_SwitchToMaterialOriginal(sender)
self:CommonSwitchToMaterial( "" );
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:Event_SwitchToMaterial1(sender)
self:CommonSwitchToMaterial( "1" );
end
------------------------------------------------------------------------------------------------------
function RigidBodyEx:Event_SwitchToMaterial2(sender)
self:CommonSwitchToMaterial( "2" );
end
------------------------------------------------------------------------------------------------------
-- Defaul state.
------------------------------------------------------------------------------------------------------
RigidBodyEx.Server.Default =
{
OnBeginState = function(self)
if (self.Properties.Physics.bRigidBody==1) then
if (self.bRigidBodyActive~=self.Properties.Physics.bRigidBodyActive) then
self.bRigidBodyActive = self.Properties.Physics.bRigidBodyActive;
self:PhysicalizeThis();
else
self:AwakePhysics(1-self.Properties.Physics.bResting);
end
end
end,
OnDamage = RigidBodyEx.OnDamage,
OnPhysicsBreak = RigidBodyEx.OnPhysicsBreak,
}
------------------------------------------------------------------------------------------------------
-- Activated state.
------------------------------------------------------------------------------------------------------
RigidBodyEx.Server.Activated =
{
OnBeginState = function(self)
if (self.Properties.Physics.bRigidBody==1 and self.bRigidBodyActive==0) then
self.bRigidBodyActive = 1;
self:PhysicalizeThis();
self:AwakePhysics(1);
end
end,
OnDamage = RigidBodyEx.OnDamage,
OnPhysicsBreak = RigidBodyEx.OnPhysicsBreak,
}
RigidBodyEx.FlowEvents =
{
Inputs =
{
Used = { RigidBodyEx.Event_Used, "bool" },
EnableUsable = { RigidBodyEx.Event_EnableUsable, "bool" },
DisableUsable = { RigidBodyEx.Event_DisableUsable, "bool" },
Activate = { RigidBodyEx.Event_Activate, "bool" },
Hide = { RigidBodyEx.Event_Hide, "bool" },
UnHide = { RigidBodyEx.Event_UnHide, "bool" },
Remove = { RigidBodyEx.Event_Remove, "bool" },
Ragdollize = { RigidBodyEx.Event_Ragdollize, "bool" },
SwitchToMaterial1 = { RigidBodyEx.Event_SwitchToMaterial1, "bool" },
SwitchToMaterial2 = { RigidBodyEx.Event_SwitchToMaterial2, "bool" },
SwitchToMaterialOriginal = { RigidBodyEx.Event_SwitchToMaterialOriginal, "bool" },
ResetHealth = { RigidBodyEx.Event_ResetHealth, "any" },
MakeVulnerable = { RigidBodyEx.Event_MakeVulnerable, "any" },
MakeInvulnerable = { RigidBodyEx.Event_MakeInvulnerable, "any" },
},
Outputs =
{
Used = "bool",
EnableUsable = "bool",
DisableUsable = "bool",
Activate = "bool",
Hide = "bool",
UnHide = "bool",
Remove = "bool",
Ragdollized = "bool",
Break = "int",
Dead = "bool",
Hit = "bool",
Health = "float",
},
}
@@ -0,0 +1,253 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
FogVolume =
{
type = "FogVolume",
Properties =
{
bActive = 1, --[0,1,1,"If true, fog volume will be enabled."]
eiVolumeType = 0, --[0,1,1,"Specifies the volume type. The following types are currently supported: 0 - Ellipsoid, 1 - Cube."
Size = { x = 1, y = 1, z = 1 },
color_Color = { x = 1, y = 1, z = 1 },
fHDRDynamic = 0, --[-10,20,0.01,"Specifies how much brighter than the default 255,255,255 white the fog is."]
bUseGlobalFogColor = 0, --[0,1,1,"If true, the Color property is ignored. Instead, the current global fog color is used."]
GlobalDensity = 1.0, --[0,1000,1,"Controls the density of the fog. The higher the value the more dense the fog and the less you'll be able to see objects behind or inside the fog volume."]
DensityOffset = 0.0, --[-1000,1000,1,"Offset fog density, used in conjunction with the GlobalDensity parameter."]
NearCutoff = 0.0, --[0,2,0.1,"Stop rendering the object, depending on camera distance to object."]
FallOffDirLong = 0.0, --[0,360,1,"Controls the longitude of the world space fall off direction of the fog. 0 represents East, rotation is counter-clockwise."]
FallOffDirLati = 90.0, --[0,360,1,"Controls the latitude of the world space fall off direction of the fog. 90 lets the fall off direction point upwards in world space."]
FallOffShift = 0.0, --[-100,100,0.1,"Controls how much to shift the fog density distribution along the fall off direction in world units (m)."]
FallOffScale = 1.0, --[-100,100,0.01,"Scales the density distribution along the fall off direction. Higher values will make the fog fall off more rapidly and generate thicker fog layers along the negative fall off direction."]
SoftEdges = 1.0, --[0,1,0.01,"Specifies a factor that is used to soften the edges of the fog volume when viewed from outside."]
RampStart = 0.0, --[0,30000,1.0,"Specifies the start distance of fog density ramp in world units (m)."]
RampEnd = 50.0, --[0,30000,1.0,"Specifies the end distance of fog density ramp in world units (m)."]
RampInfluence = 0.0, --[0,1,0.0,"Controls the influence of fog density ramp."]
WindInfluence = 1.0, --[0,20,0.0,"Controls the influence of the wind."]
DensityNoiseScale = 1.0, --[0.0,10.0,0.0,"Scales the noise for the density."]
DensityNoiseOffset = 1.0, --[-2,2,0.0,"Offsets the noise for the density."]
DensityNoiseTimeFrequency = 0.0, --[0,1,0.0,"Controls the time frequency of the noise for the density."]
DensityNoiseFrequency = { x = 10, y = 10, z = 10 }, --[1,1000,0.1,"Controls the spatial frequency of the noise for the density."]
bIgnoresVisAreas = 0, --[0,1,0,"Controls whether this entity should respond to visareas."]
bAffectsThisAreaOnly = 0, --[0,1,0,"Set this parameter to false to make this entity affect in multiple visareas."]
},
Fader =
{
fadeTime = 0.0,
fadeToValue = 0.0,
},
Editor =
{
Model = "Editor/Objects/invisiblebox.cgf",
Icon = "FogVolume.bmp",
ShowBounds = 1,
},
}
function FogVolume:OnSpawn()
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY, 0);
self:SetFlags(ENTITY_FLAG_NO_PROXIMITY, 0);
end
-------------------------------------------------------
function FogVolume:InitFogVolumeProperties()
--System.Log( "FogVolume:InitFogVolumeProperties" )
local props = self.Properties;
self:LoadFogVolume( 0, self.Properties );
end;
-------------------------------------------------------
function FogVolume:CreateFogVolume()
--System.Log( "FogVolume:CreateFogVolume" )
self:InitFogVolumeProperties()
self.active = true;
end
-------------------------------------------------------
function FogVolume:DeleteFogVolume()
--System.Log( "FogVolume:DeleteFogVolume" )
self:FreeSlot( 0 );
self.active = false;
end
-------------------------------------------------------
function FogVolume:OnInit()
self.active = false;
if( self.Properties.bActive == 1 ) then
self:CreateFogVolume();
end
end
-------------------------------------------------------
function FogVolume:CheckMove()
end
-------------------------------------------------------
function FogVolume:OnShutDown()
end
-------------------------------------------------------
function FogVolume:OnPropertyChange()
--System.Log( "FogVolume:OnPropertyChange" )
if( self.Properties.bActive == 1 ) then
self:CreateFogVolume();
else
self:DeleteFogVolume();
end
end
-------------------------------------------------------
-- optimization for common animated trackview properties, to avoid fully recreating everything on every animated frame
function FogVolume:OnPropertyAnimated( name )
local changeTakenCareOf = false;
if (name=="GlobalDensity") then
self:FadeGlobalDensity(0, 0, self.Properties.GlobalDensity); -- using fade with 0 time as there is not a 'set' function.
changeTakenCareOf = true;
end
return changeTakenCareOf;
end
-------------------------------------------------------
function FogVolume:OnReset()
self.active = false;
if( self.Properties.bActive == 1 ) then
self:CreateFogVolume();
end
end
-------------------------------------------------------
-- Hide Event
-------------------------------------------------------
function FogVolume:Event_Hide()
self:DeleteFogVolume();
BroadcastEvent(self, "Hide");
end
-------------------------------------------------------
-- Show Event
-------------------------------------------------------
function FogVolume:Event_Show()
self:CreateFogVolume();
BroadcastEvent(self, "Show");
end
-------------------------------------------------------
-- Fade Event
-------------------------------------------------------
function FogVolume:Event_Fade()
--System.Log("Do Fading");
self:FadeGlobalDensity(0, self.Fader.fadeTime, self.Fader.fadeToValue);
end
-------------------------------------------------------
-- Fade Time Event
-------------------------------------------------------
function FogVolume:Event_FadeTime(i, time)
--System.Log("Fade time "..tostring(time));
self.Fader.fadeTime = time;
end
-------------------------------------------------------
-- Fade Value Event
-------------------------------------------------------
function FogVolume:Event_FadeValue(i, val)
--System.Log("Fade val "..tostring(val));
self.Fader.fadeToValue = val;
end
-------------------------------------------------------
-- Set Enabled Event
-------------------------------------------------------
function FogVolume:Event_Enabled(i, enable)
if (enable) then
self:CreateFogVolume();
self:ActivateOutput( "Enabled", true );
else
self:DeleteFogVolume();
self:ActivateOutput( "Enabled", false );
end
end
-------------------------------------------------------
-- Set GlobalDensity Event
-------------------------------------------------------
function FogVolume:Event_SetGlobalDensity(i, val)
self.Properties.GlobalDensity = val;
self:FadeGlobalDensity(0, 0, self.Properties.GlobalDensity);
end
-------------------------------------------------------
-- Set DensityNoiseOffset Event
-------------------------------------------------------
function FogVolume:Event_SetDensityNoiseOffset(i, val)
self.Properties.DensityNoiseOffset = val;
self:CreateFogVolume();
end
-------------------------------------------------------
-- Set DensityNoiseScale Event
-------------------------------------------------------
function FogVolume:Event_SetDensityNoiseScale(i, val)
self.Properties.DensityNoiseScale = val;
self:CreateFogVolume();
end
-------------------------------------------------------
-- Set WindInfluence Event
-------------------------------------------------------
function FogVolume:Event_SetWindInfluence(i, val)
self.Properties.WindInfluence = val;
self:CreateFogVolume();
end
-------------------------------------------------------
-- Serialization
-------------------------------------------------------
function FogVolume:OnLoad(table)
if(self.active and not table.active) then
self:DeleteFogVolume();
elseif(not self.active and table.active) then
self:CreateFogVolume();
end
self.active = table.active;
end
-------------------------------------------------------
function FogVolume:OnSave(table)
table.active = self.active;
end
-------------------------------------------------------
FogVolume.FlowEvents =
{
Inputs =
{
AO_Enabled = { FogVolume.Event_Enabled, "bool" },
EV_Density = { FogVolume.Event_SetGlobalDensity, "float" },
EV_DensityNoiseOffset = { FogVolume.Event_SetDensityNoiseOffset, "float" },
EV_DensityNoiseScale = { FogVolume.Event_SetDensityNoiseScale, "float" },
EV_WindInfluence = { FogVolume.Event_SetWindInfluence, "float" },
},
Outputs =
{
Enabled = "bool"
},
}
@@ -0,0 +1,181 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
Script.ReloadScript("scripts/Utils/EntityUtils.lua")
GeomCache =
{
Properties = {
geomcacheFile = "EngineAssets/GeomCaches/defaultGeomCache.cax",
bPlaying = 0,
fStartTime = 0,
bLooping = 0,
objectStandIn = "",
materialStandInMaterial = "",
objectFirstFrameStandIn = "",
materialFirstFrameStandInMaterial = "",
objectLastFrameStandIn = "",
materialLastFrameStandInMaterial = "",
fStandInDistance = 0,
fStreamInDistance = 0,
Physics = {
bPhysicalize = 0,
}
},
Editor={
Icon = "animobject.bmp",
IconOnTop = 1,
},
bPlaying = 0,
currentTime = 0,
precacheTime = 0,
bPrecachedOutputTriggered = false,
}
function GeomCache:OnLoad(table)
self.currentTime = table.currentTime;
end
function GeomCache:OnSave(table)
table.currentTime = self.currentTime;
end
function GeomCache:OnSpawn()
self.currentTime = self.Properties.fStartTime;
self:SetFromProperties();
end
function GeomCache:OnReset()
self.currentTime = self.Properties.fStartTime;
self.bPrecachedOutputTriggered = true;
self:SetFromProperties();
end
function GeomCache:SetFromProperties()
local Properties = self.Properties;
if (Properties.geomcacheFile == "") then
do return end;
end
self:LoadGeomCache(0, Properties.geomcacheFile);
self.bPlaying = Properties.bPlaying;
if (self.bPlaying == 0) then
self.currentTime = Properties.fStartTime;
end
self:SetGeomCachePlaybackTime(self.currentTime);
self:SetGeomCacheParams(Properties.bLooping, Properties.objectStandIn, Properties.materialStandInMaterial, Properties.objectFirstFrameStandIn,
Properties.materialFirstFrameStandInMaterial, Properties.objectLastFrameStandIn, Properties.materialLastFrameStandInMaterial,
Properties.fStandInDistance, Properties.fStreamInDistance);
self:SetGeomCacheStreaming(false, 0);
if (Properties.Physics.bPhysicalize == 1) then
local tempPhysParams = EntityCommon.TempPhysParams;
self:Physicalize(0, PE_ARTICULATED, tempPhysParams);
end
self:Activate(1);
end
function GeomCache:PhysicalizeThis()
local Physics = self.Properties.Physics;
EntityCommon.PhysicalizeRigid(self, 0, Physics, false);
end
function GeomCache:OnUpdate(dt)
if (self.bPlaying == 1) then
self:SetGeomCachePlaybackTime(self.currentTime);
end
if (self:IsGeomCacheStreaming() and not self.bPrecachedOutputTriggered) then
local precachedTime = self:GetGeomCachePrecachedTime();
if (precachedTime >= self.precacheTime) then
self:ActivateOutput("Precached", true);
self.bPrecachedOutputTriggered = true;
end
end
if (self.bPlaying == 1) then
self.currentTime = self.currentTime + dt;
end
end
function GeomCache:OnPropertyChange()
self:SetFromProperties();
end
function GeomCache:Event_Start(sender, val)
self.bPlaying = 1;
end
function GeomCache:Event_Stop(sender, value)
self.bPlaying = 0;
end
function GeomCache:Event_SetTime(sender, value)
self.currentTime = value;
end
function GeomCache:Event_StartStreaming(sender, value)
self.bPrecachedOutputTriggered = false;
self:SetGeomCacheStreaming(true, self.currentTime);
end
function GeomCache:Event_StopStreaming(sender, value)
self:SetGeomCacheStreaming(false, 0);
end
function GeomCache:Event_PrecacheTime(sender, value)
self.precacheTime = value;
end
function GeomCache:Event_Hide(sender, value)
self:Hide(1);
end
function GeomCache:Event_Unhide(sender, value)
self:Hide(0);
end
function GeomCache:Event_StopDrawing(sender, value)
self:SetGeomCacheDrawing(false);
end
function GeomCache:Event_StartDrawing(sender, value)
self:SetGeomCacheDrawing(true);
end
GeomCache.FlowEvents =
{
Inputs =
{
Start = { GeomCache.Event_Start, "any" },
Stop = { GeomCache.Event_Stop, "any" },
SetTime = { GeomCache.Event_SetTime, "float" },
StartStreaming = { GeomCache.Event_StartStreaming, "any" },
StopStreaming = { GeomCache.Event_StopStreaming, "any" },
PrecacheTime = { GeomCache.Event_PrecacheTime, "float" },
Hide = { GeomCache.Event_Hide, "any" },
Unhide = { GeomCache.Event_Unhide, "any" },
StopDrawing = { GeomCache.Event_StopDrawing, "any" },
StartDrawing = { GeomCache.Event_StartDrawing, "any" },
},
Outputs =
{
Precached = "bool",
},
}
@@ -0,0 +1,382 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
-- audio area ambience entity - to be attached to an area
-- used for convenient implementation of area based audio ambiences
AudioAreaAmbience = {
type = "AudioAreaAmbience",
Editor = {
Model = "Editor/Objects/Sound.cgf",
Icon = "AudioAreaAmbience.bmp",
},
Properties = {
bEnabled = true,
audioTriggerPlayTrigger = "",
audioTriggerStopTrigger = "",
audioRTPCRtpc = "",
audioEnvironmentEnvironment = "",
eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_IGNORE,
fRtpcDistance = 5.0,
fEnvironmentDistance = 5.0,
},
fFadeValue = 0.0,
nState = 0, -- 0 = far, 1 = near, 2 = inside
fFadeOnUnregister = 1.0,
hOnTriggerID = nil,
hOffTriggerID = nil,
hCurrentOnTriggerID = nil,
hCurrentOffTriggerID = nil, -- only used in OnPropertyChange()
hRtpcID = nil,
hEnvironmentID = nil,
tObstructionType = {},
bIsHidden = false,
bIsPlaying = false,
bOriginalEnabled = true,
}
----------------------------------------------------------------------------------------
function AudioAreaAmbience:_LookupControlIDs()
self.hOnTriggerID = AudioUtils.LookupTriggerID(self.Properties.audioTriggerPlayTrigger);
self.hOffTriggerID = AudioUtils.LookupTriggerID(self.Properties.audioTriggerStopTrigger);
self.hRtpcID = AudioUtils.LookupRtpcID(self.Properties.audioRTPCRtpc);
self.hEnvironmentID = AudioUtils.LookupAudioEnvironmentID(self.Properties.audioEnvironmentEnvironment);
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:_LookupObstructionSwitchIDs()
-- cache the obstruction switch and state IDs
self.tObstructionType = AudioUtils.LookupObstructionSwitchAndStates();
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:_SetObstruction()
local nStateIdx = self.Properties.eiSoundObstructionType + 1;
self:SetAudioObstructionCalcType(self.Properties.eiSoundObstructionType, self:GetDefaultAuxAudioProxyID());
if ((self.tObstructionType.hSwitchID ~= nil) and (self.tObstructionType.tStateIDs[nStateIdx] ~= nil)) then
self:SetAudioSwitchState(self.tObstructionType.hSwitchID, self.tObstructionType.tStateIDs[nStateIdx], self:GetDefaultAuxAudioProxyID());
end
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:_DisableObstruction()
-- Ignore is at index 1 (because Lua uses 1-based indexing)
local nStateIdx = 1;
self:SetAudioObstructionCalcType(AUDIO_OBSTRUCTION_TYPE_IGNORE, self:GetDefaultAuxAudioProxyID());
if ((self.tObstructionType.hSwitchID ~= nil) and (self.tObstructionType.tStateIDs[nStateIdx] ~= nil)) then
self:SetAudioSwitchState(self.tObstructionType.hSwitchID, self.tObstructionType.tStateIDs[nStateIdx], self:GetDefaultAuxAudioProxyID());
end
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:_UpdateParameters()
-- Set the distances as the very first thing!
self:SetFadeDistance(self.Properties.fRtpcDistance);
self:SetEnvironmentFadeDistance(self.Properties.fEnvironmentDistance);
if (self.Properties.bEnabled) then
if (self.hEnvironmentID ~= nil) then
self:SetAudioEnvironmentID(self.hEnvironmentID);
end
else
self:SetAudioEnvironmentID(INVALID_AUDIO_ENVIRONMENT_ID);
end
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:_UpdateRtpc()
if (self.hRtpcID ~= nil) then
self:SetAudioRtpcValue(self.hRtpcID, self.fFadeValue, self:GetDefaultAuxAudioProxyID());
end
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:OnSpawn()
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY, 0);
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:OnLoad(load)
self.Properties = load.Properties;
self.fFadeValue = load.fFadeValue;
self.fFadeOnUnregister = load.fFadeOnUnregister;
self.nState = 0; -- We start out being far, in a subsequent update we will determine our actual state!
self:_SetObstruction();
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:OnPostLoad()
self:_UpdateParameters();
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:OnSave(save)
save.Properties = self.Properties;
save.fFadeValue = self.fFadeValue;
save.fFadeOnUnregister = self.fFadeOnUnregister;
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:OnPropertyChange()
if (self.Properties.eiSoundObstructionType < AUDIO_OBSTRUCTION_TYPE_IGNORE) then
self.Properties.eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_IGNORE;
elseif (self.Properties.eiSoundObstructionType > AUDIO_OBSTRUCTION_TYPE_MULTI) then
self.Properties.eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_MULTI;
end
self:_LookupControlIDs();
self:_UpdateParameters();
self:ResetAudioRtpcValues(self:GetDefaultAuxAudioProxyID());
self:SetCurrentAudioEnvironments();
self:SetAudioProxyOffset(g_Vectors.v000, self:GetDefaultAuxAudioProxyID());
if (self.nState == 1) then -- near
self:_SetObstruction();
elseif (self.nState == 2) then -- inside
self:_DisableObstruction();
end
if ((self.bIsPlaying) and (self.hCurrentOnTriggerID ~= self.hOnTriggerID)) then
-- Stop a possibly playing instance if the on-trigger changed!
self:StopAudioTrigger(self.hCurrentOnTriggerID, self:GetDefaultAuxAudioProxyID());
self.hCurrentOnTriggerID = self.hOnTriggerID;
self.bIsPlaying = false;
self.bHasMoved = false;
end
if (not self.bIsPlaying) then
-- Try to play, if disabled, hidden or invalid on-trigger Play() will fail!
self:Play();
end
if (not self.Properties.bEnabled and ((self.bOriginalEnabled) or (self.hCurrentOffTriggerID ~= self.hOffTriggerID))) then
self.hCurrentOffTriggerID = self.hOffTriggerID;
self:Stop(); -- stop if disabled, either stops running StartTrigger or executes StopTrigger!
end
self.bOriginalEnabled = self.Properties.bEnabled;
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:OnReset(bToGame)
if (bToGame) then
-- store the entity's "bEnabled" property's value so we can adjust back to it if changed over the course of the game
self.bOriginalEnabled = self.Properties.bEnabled;
-- re-execute this AAA once upon entering game mode
self:Stop();
self:Play();
else
self.Properties.bEnabled = self.bOriginalEnabled;
end
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:Play()
if ((self.Properties.bEnabled) and (not self.bIsHidden) and ((self.nState == 1) or (self.nState == 2))) then
if (self.hOnTriggerID ~= nil) then
self:SetCurrentAudioEnvironments();
self:ExecuteAudioTrigger(self.hOnTriggerID, self:GetDefaultAuxAudioProxyID());
self.bIsPlaying = true;
self.hCurrentOnTriggerID = self.hOnTriggerID;
end
end
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:Stop()
if ((self.Properties.bEnabled) and (not self.bIsHidden) and ((self.nState == 1) or (self.nState == 2))) then
-- cannot check against "self.bIsPlaying" otherwise we won't execute the StopTrigger if there's no StartTrigger set!
if (self.hOffTriggerID ~= nil) then
self:ExecuteAudioTrigger(self.hOffTriggerID, self:GetDefaultAuxAudioProxyID());
elseif (self.hOnTriggerID ~= nil) then
self:StopAudioTrigger(self.hOnTriggerID, self:GetDefaultAuxAudioProxyID());
end
end
self.bIsPlaying = false;
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:StopAll()
if (self.hOnTriggerID ~= nil) then
self:StopAudioTrigger(self.hOnTriggerID, self:GetDefaultAuxAudioProxyID());
end
if (self.hOffTriggerID ~= nil) then
self:StopAudioTrigger(self.hOffTriggerID, self:GetDefaultAuxAudioProxyID());
end
self.bIsPlaying = false;
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:CliSrv_OnInit()
self.nState = 0;
self.fFadeValue = 0.0;
self.fFadeOnUnregister = 1.0;
self:SetFlags(ENTITY_FLAG_VOLUME_SOUND, 0);
self:_UpdateParameters();
self.bIsPlaying = false;
self:NetPresent(0);
end
----------------------------------------------------------------------------------------
function AudioAreaAmbience:UpdateFadeValue(player, fFade, fDistSq)
if (not(self.Properties.bEnabled) or (fFade == 0.0 and fDistSq == 0.0)) then
self.fFadeValue = 0.0;
self:_UpdateRtpc();
do return end;
end
if (self.Properties.fRtpcDistance > 0.0) then
if (self.nState == 2) then
if (self.fFadeValue ~= fFade) then
self.fFadeValue = math.abs(fFade);
self:_UpdateRtpc();
end
else
local fLocalFade = 1.0 - (math.sqrt(fDistSq) / self.Properties.fRtpcDistance);
self.fFadeValue = math.max(0, fLocalFade);
self:_UpdateRtpc();
end
end
end
----------------------------------------------------------------------------------------
AudioAreaAmbience.Server = {
OnInit = function(self)
self:CliSrv_OnInit();
end,
OnShutDown = function(self)
end,
}
----------------------------------------------------------------------------------------
AudioAreaAmbience.Client = {
OnInit = function(self)
self:RegisterForAreaEvents(1);
self:_LookupControlIDs();
self:_LookupObstructionSwitchIDs();
self:_SetObstruction();
self:CliSrv_OnInit();
end,
OnShutDown = function(self)
self:StopAll();
self.nState = 0;
self:RegisterForAreaEvents(0);
end,
OnHidden = function(self)
self:StopAll();
self.bIsHidden = true;
end,
OnUnHidden = function(self)
self.bIsHidden = false;
self:Play();
end,
OnAudioListenerEnterNearArea = function(self, player, nAreaID, fFade)
if (self.nState == 0) then
self.nState = 1;
self:Play();
self.fFadeValue = 0.0;
self:_UpdateRtpc();
end
end,
OnAudioListenerMoveNearArea = function(self, player, areaId, fFade, fDistsq)
self.nState = 1;
self:UpdateFadeValue(player, fFade, fDistsq);
end,
OnAudioListenerEnterArea = function(self, player, areaId, fFade)
if (self.nState == 0) then
-- possible if the listener is teleported or gets spawned inside the area
-- technically, the listener enters the Near Area and the Inside Area at the same time
self.nState = 2;
self:Play();
else
self.nState = 2;
end
self.fFadeValue = 1.0;
self:_UpdateRtpc();
self:_DisableObstruction();
end,
OnAudioListenerProceedFadeArea = function(self, player, areaId, fExternalFade)
-- fExternalFade holds the fade value which was calculated by an inner, higher priority area
-- in the AreaManager to fade out the outer sound dependent on the largest fade distance of all attached entities
if (fExternalFade > 0.0) then
self.nState = 2;
self:UpdateFadeValue(player, fExternalFade, 0.0);
else
self:UpdateFadeValue(player, 0.0, 0.0);
end
end,
OnAudioListenerLeaveArea = function(self, player, nAreaID, fFade)
self.nState = 1;
self:_SetObstruction();
end,
OnAudioListenerLeaveNearArea = function(self, player, nAreaID, fFade)
self:Stop();
self.nState = 0;
self.fFadeValue = 0.0;
self:_UpdateRtpc();
end,
OnUnBindThis = function(self)
self.nState = 0;
end,
OnSoundDone = function(self, hTriggerID)
if (self.hOnTriggerID == hTriggerID) then
self:ActivateOutput("Done", true);
end
end,
}
----------------------------------------------------------------------------------------
-- Event Handlers
----------------------------------------------------------------------------------------
function AudioAreaAmbience:Event_Enable(sender)
self.Properties.bEnabled = true;
self:OnPropertyChange();
end
function AudioAreaAmbience:Event_Disable(sender)
self.Properties.bEnabled = false;
self:OnPropertyChange();
end
AudioAreaAmbience.FlowEvents =
{
Inputs =
{
Enable = { AudioAreaAmbience.Event_Enable, "bool" },
Disable = { AudioAreaAmbience.Event_Disable, "bool" },
},
Outputs =
{
Done = "bool",
},
}
@@ -0,0 +1,265 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
-- audio area entity - to be attached to an area
-- reports a normalized (0-1) fade value depending on the listener's distance to the area
AudioAreaEntity = {
type = "AudioAreaEntity",
Editor = {
Model = "Editor/Objects/Sound.cgf",
Icon = "AudioAreaEntity.bmp",
},
Properties = {
bEnabled = true,
audioEnvironmentEnvironment = "",
eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_IGNORE,
fFadeDistance = 5.0,
fEnvironmentDistance = 5.0,
},
fFadeValue = 0.0,
nState = 0, -- 0 = far, 1 = near, 2 = inside
fFadeOnUnregister = 1.0,
hEnvironmentID = nil,
tObstructionType = {},
}
----------------------------------------------------------------------------------------
function AudioAreaEntity:_ActivateOutput(sPortName, value)
if (self.Properties.bEnabled) then
self:ActivateOutput(sPortName, value);
end
end
----------------------------------------------------------------------------------------
function AudioAreaEntity:_UpdateParameters()
-- Set the distances as the very first thing!
self:SetFadeDistance(self.Properties.fFadeDistance);
self:SetEnvironmentFadeDistance(self.Properties.fEnvironmentDistance);
if (self.Properties.bEnabled) then
self.hEnvironmentID = AudioUtils.LookupAudioEnvironmentID(self.Properties.audioEnvironmentEnvironment);
if (self.hEnvironmentID ~= nil) then
self:SetAudioEnvironmentID(self.hEnvironmentID);
end
else
self:SetAudioEnvironmentID(INVALID_AUDIO_ENVIRONMENT_ID);
end
end
----------------------------------------------------------------------------------------
function AudioAreaEntity:_LookupObstructionSwitchIDs()
-- cache the obstruction switch and state IDs
self.tObstructionType = AudioUtils.LookupObstructionSwitchAndStates();
end
----------------------------------------------------------------------------------------
function AudioAreaEntity:_SetObstruction()
local nStateIdx = self.Properties.eiSoundObstructionType + 1;
self:SetAudioObstructionCalcType(self.Properties.eiSoundObstructionType, self:GetDefaultAuxAudioProxyID());
if ((self.tObstructionType.hSwitchID ~= nil) and (self.tObstructionType.tStateIDs[nStateIdx] ~= nil)) then
self:SetAudioSwitchState(self.tObstructionType.hSwitchID, self.tObstructionType.tStateIDs[nStateIdx], self:GetDefaultAuxAudioProxyID());
end
end
----------------------------------------------------------------------------------------
function AudioAreaEntity:OnSpawn()
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY, 0);
end
----------------------------------------------------------------------------------------
function AudioAreaEntity:OnLoad(load)
self.Properties = load.Properties;
self.fFadeOnUnregister = load.fFadeOnUnregister;
self:_SetObstruction();
self.nState = 0;
self.fFadeValue = 0.0;
end
----------------------------------------------------------------------------------------
function AudioAreaEntity:OnPostLoad()
self:_UpdateParameters();
end
----------------------------------------------------------------------------------------
function AudioAreaEntity:OnSave(save)
save.Properties = self.Properties;
save.fFadeOnUnregister = self.fFadeOnUnregister;
end
----------------------------------------------------------------------------------------
function AudioAreaEntity:OnPropertyChange()
self:_UpdateParameters();
if (self.Properties.eiSoundObstructionType < AUDIO_OBSTRUCTION_TYPE_IGNORE) then
self.Properties.eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_IGNORE;
elseif (self.Properties.eiSoundObstructionType > AUDIO_OBSTRUCTION_TYPE_MULTI) then
self.Properties.eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_MULTI;
end
self:ResetAudioRtpcValues(self:GetDefaultAuxAudioProxyID());
self:_SetObstruction();
end
----------------------------------------------------------------------------------------
function AudioAreaEntity:CliSrv_OnInit()
self.nState = 0;
self.fFadeValue = 0.0;
self.fFadeOnUnregister = 1.0;
self:SetFlags(ENTITY_FLAG_VOLUME_SOUND, 0);
self:_UpdateParameters();
end
----------------------------------------------------------------------------------------
function AudioAreaEntity:UpdateFadeValue(player, fFade, fDistSq)
if (not(self.Properties.bEnabled) or (fFade == 0.0 and fDistSq == 0.0)) then
if (self.fFadeValue ~= 0.0) then
self:_ActivateOutput("FadeValue", 0.0);
end
self.fFadeValue = 0.0;
do return end;
end
if (self.Properties.fFadeDistance > 0.0) then
if (self.nState == 2) then
if (self.fFadeValue ~= fFade) then
self.fFadeValue = math.abs(fFade);
self:_ActivateOutput("FadeValue", self.fFadeValue);
end
else
local fLocalFade = 1.0 - (math.sqrt(fDistSq) / self.Properties.fFadeDistance);
self.fFadeValue = math.max(0, fLocalFade);
self:_ActivateOutput("FadeValue", self.fFadeValue);
end
end
end
----------------------------------------------------------------------------------------
AudioAreaEntity.Server = {
OnInit = function(self)
self:CliSrv_OnInit();
end,
OnShutDown = function(self)
end,
}
----------------------------------------------------------------------------------------
AudioAreaEntity.Client = {
OnInit = function(self)
self:RegisterForAreaEvents(1);
self:_LookupObstructionSwitchIDs();
self:_SetObstruction();
self:CliSrv_OnInit();
end,
OnShutDown = function(self)
self.nState = 0;
self:RegisterForAreaEvents(0);
end,
OnAudioListenerEnterNearArea = function(self, player, nAreaID, fFade)
if (self.nState == 0) then
self:_SetObstruction();
self:_ActivateOutput("OnFarToNear", true);
elseif (self.nState == 2) then
self:_ActivateOutput("OnInsideToNear", true);
end
self.nState = 1;
self.fFadeValue = 0.0;
self:_ActivateOutput("FadeValue", self.fFadeValue);
end,
OnAudioListenerMoveNearArea = function(self, player, areaId, fFade, fDistsq)
self.nState = 1;
self:UpdateFadeValue(player, fFade, fDistsq);
end,
OnAudioListenerEnterArea = function(self, player, areaId, fFade)
if (self.nState == 0) then
-- possible if the listener is teleported or gets spawned inside the area
-- technically, the listener enters the Near Area and the Inside Area at the same time
-- however, in this case the AreaManager is responsible to first call OnEnterNear and then OnEnter so this is technically circumventing a possible bug :)
self:_SetObstruction();
self:_ActivateOutput("OnFarToNear", true);
end
self.nState = 2;
self.fFadeValue = 1.0;
self:_ActivateOutput("OnNearToInside", true);
self:_ActivateOutput("FadeValue", self.fFadeValue);
end,
OnAudioListenerProceedFadeArea = function(self, player, areaId, fExternalFade)
-- fExternalFade holds the fade value which was calculated by an inner, higher priority area
-- in the AreaManager to fade out the outer sound dependent on the largest fade distance of all attached entities
if (fExternalFade > 0.0) then
self.nState = 2;
self:UpdateFadeValue(player, fExternalFade, 0.0);
else
self:UpdateFadeValue(player, 0.0, 0.0);
end
end,
OnAudioListenerLeaveArea = function(self, player, nAreaID, fFade)
self.nState = 1;
self:_ActivateOutput("OnInsideToNear", true);
end,
OnAudioListenerLeaveNearArea = function(self, player, nAreaID, fFade)
self.nState = 0;
self.fFadeValue = 0.0;
self:_ActivateOutput("OnNearToFar", true);
self:_ActivateOutput("FadeValue", self.fFadeValue);
end,
OnUnBindThis = function(self)
self.nState = 0;
end,
}
----------------------------------------------------------------------------------------
-- Event Handlers
----------------------------------------------------------------------------------------
function AudioAreaEntity:Event_Enable(sender)
self.Properties.bEnabled = true;
self:OnPropertyChange();
end
function AudioAreaEntity:Event_Disable(sender)
self.Properties.bEnabled = false;
self:OnPropertyChange();
end
AudioAreaEntity.FlowEvents =
{
Inputs =
{
Enable = { AudioAreaEntity.Event_Enable, "bool" },
Disable = { AudioAreaEntity.Event_Disable, "bool" },
},
Outputs =
{
FadeValue = "float",
OnFarToNear = "bool",
OnNearToInside = "bool",
OnInsideToNear = "bool",
OnNearToFar = "bool",
},
}
@@ -0,0 +1,386 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
-- audio area ambience entity - to be attached to an area
-- used for convenient implementation of area based audio ambiences
AudioAreaRandom = {
type = "AudioAreaRandom",
Editor = {
Model = "Editor/Objects/Sound.cgf",
Icon = "AudioAreaRandom.bmp",
},
Properties = {
bEnabled = true,
bMoveWithEntity = false,
audioTriggerPlayTrigger = "",
audioTriggerStopTrigger = "",
audioRTPCRtpc = "",
eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_IGNORE,
fRtpcDistance = 5.0,
fRadiusRandom = 10.0,
fMinDelay = 1,
fMaxDelay = 2,
},
fFadeValue = 0.0,
nState = 0, -- 0 = far, 1 = near, 2 = inside
hOnTriggerID = nil,
hOffTriggerID = nil,
hCurrentOnTriggerID = nil,
hCurrentOffTriggerID = nil, -- only used in OnPropertyChange()
hRtpcID = nil,
tObstructionType = {},
bIsHidden = false,
bIsPlaying = false,
bHasMoved = false,
bOriginalEnabled = true,
}
----------------------------------------------------------------------------------------
function AudioAreaRandom:_LookupControlIDs()
self.hOnTriggerID = AudioUtils.LookupTriggerID(self.Properties.audioTriggerPlayTrigger);
self.hOffTriggerID = AudioUtils.LookupTriggerID(self.Properties.audioTriggerStopTrigger);
self.hRtpcID = AudioUtils.LookupRtpcID(self.Properties.audioRTPCRtpc);
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:_LookupObstructionSwitchIDs()
-- cache the obstruction switch and state IDs
self.tObstructionType = AudioUtils.LookupObstructionSwitchAndStates();
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:_SetObstruction()
local nStateIdx = self.Properties.eiSoundObstructionType + 1;
self:SetAudioObstructionCalcType(self.Properties.eiSoundObstructionType, self:GetDefaultAuxAudioProxyID());
if ((self.tObstructionType.hSwitchID ~= nil) and (self.tObstructionType.tStateIDs[nStateIdx] ~= nil)) then
self:SetAudioSwitchState(self.tObstructionType.hSwitchID, self.tObstructionType.tStateIDs[nStateIdx], self:GetDefaultAuxAudioProxyID());
end
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:_UpdateParameters()
self:SetFadeDistance(self.Properties.fRtpcDistance);
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:_UpdateRtpc()
if (self.hRtpcID ~= nil) then
self:SetAudioRtpcValue(self.hRtpcID, self.fFadeValue, self:GetDefaultAuxAudioProxyID());
end
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:_GenerateOffset()
local offset = {x = 0, y = 0, z = 0}
offset.x = randomF(-1, 1);
offset.y = randomF(-1, 1);
NormalizeVector(offset);
ScaleVectorInPlace(offset, randomF(0, self.Properties.fRadiusRandom));
return offset;
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:OnSpawn()
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY, 0);
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:OnLoad(load)
self.Properties = load.Properties;
self.fFadeValue = load.fFadeValue;
self.nState = 0; -- We start out being far, in a subsequent update we will determine our actual state!
self:_SetObstruction();
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:OnPostLoad()
self:_UpdateParameters();
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:OnSave(save)
save.Properties = self.Properties;
save.fFadeValue = self.fFadeValue;
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:OnPropertyChange()
if (self.Properties.eiSoundObstructionType < AUDIO_OBSTRUCTION_TYPE_IGNORE) then
self.Properties.eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_IGNORE;
elseif (self.Properties.eiSoundObstructionType > AUDIO_OBSTRUCTION_TYPE_MULTI) then
self.Properties.eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_MULTI;
end
self:_LookupControlIDs();
self:_UpdateParameters();
self:_SetObstruction();
self:ResetAudioRtpcValues(self:GetDefaultAuxAudioProxyID());
self:SetCurrentAudioEnvironments();
self:SetAudioProxyOffset(g_Vectors.v000, self:GetDefaultAuxAudioProxyID());
self:AuxAudioProxiesMoveWithEntity(self.Properties.bMoveWithEntity);
if ((self.bIsPlaying) and (self.hCurrentOnTriggerID ~= self.hOnTriggerID)) then
-- Stop a possibly playing instance if the on-trigger changed!
self:StopAudioTrigger(self.hCurrentOnTriggerID, self:GetDefaultAuxAudioProxyID());
self.hCurrentOnTriggerID = self.hOnTriggerID;
self.bIsPlaying = false;
self.bHasMoved = false;
self:KillTimer(0);
end
if (not self.bIsPlaying) then
-- Try to play, if disabled, hidden or invalid on-trigger Play() will fail!
self:Play();
end
if (not self.Properties.bEnabled and ((self.bOriginalEnabled) or (self.hCurrentOffTriggerID ~= self.hOffTriggerID))) then
self.hCurrentOffTriggerID = self.hOffTriggerID;
self:Stop(); -- stop if disabled, either stops running StartTrigger or executes StopTrigger!
end
self.bOriginalEnabled = self.Properties.bEnabled;
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:OnReset(bToGame)
if (bToGame) then
-- store the entity's "bEnabled" property's value so we can adjust back to it if changed over the course of the game
self.bOriginalEnabled = self.Properties.bEnabled;
-- re-execute this AAR once upon entering game mode
self:Stop();
self:Play();
else
self.Properties.bEnabled = self.bOriginalEnabled;
end
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:Play()
if ((self.Properties.bEnabled) and (not self.bIsHidden) and ((self.nState == 1) or (self.nState == 2))) then
if (self.hOnTriggerID ~= nil) then
local offset = self:_GenerateOffset();
if (LengthSqVector(offset) > 0.00001) then-- offset is longer than 1cm
self:SetAudioProxyOffset(offset, self:GetDefaultAuxAudioProxyID());
self:SetCurrentAudioEnvironments();
elseif (self.bHasMoved) then
self:SetCurrentAudioEnvironments();
end
self:ExecuteAudioTrigger(self.hOnTriggerID, self:GetDefaultAuxAudioProxyID());
self.bIsPlaying = true;
self.bHasMoved = false;
self.hCurrentOnTriggerID = self.hOnTriggerID;
self:SetTimer(0, 1000 * randomF(self.Properties.fMinDelay, self.Properties.fMaxDelay));
end
end
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:Stop()
if ((self.Properties.bEnabled) and (not self.bIsHidden) and ((self.nState == 1) or (self.nState == 2))) then
-- Cannot check against "self.bIsPlaying" otherwise we won't execute the StopTrigger if there's no StartTrigger set!
if (self.hOffTriggerID ~= nil) then
local offset = self:_GenerateOffset();
if (LengthSqVector(offset) > 0.00001) then-- offset is longer than 1cm
self:SetAudioProxyOffset(offset, self:GetDefaultAuxAudioProxyID());
self:SetCurrentAudioEnvironments();
elseif (self.bHasMoved) then
self:SetCurrentAudioEnvironments();
end
self:ExecuteAudioTrigger(self.hOffTriggerID, self:GetDefaultAuxAudioProxyID());
elseif (self.hOnTriggerID ~= nil) then
self:StopAudioTrigger(self.hOnTriggerID, self:GetDefaultAuxAudioProxyID());
end
end
self.bIsPlaying = false;
self.bHasMoved = false;
self:KillTimer(0);
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:StopAll()
if (self.hOnTriggerID ~= nil) then
self:StopAudioTrigger(self.hOnTriggerID, self:GetDefaultAuxAudioProxyID());
end
if (self.hOffTriggerID ~= nil) then
self:StopAudioTrigger(self.hOffTriggerID, self:GetDefaultAuxAudioProxyID());
end
self.bIsPlaying = false;
self:KillTimer(0);
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:CliSrv_OnInit()
self.nState = 0;
self.fFadeValue = 0.0;
self:SetFlags(ENTITY_FLAG_VOLUME_SOUND, 0);
self:_UpdateParameters();
self.bIsPlaying = false;
self:NetPresent(0);
self:AuxAudioProxiesMoveWithEntity(self.Properties.bMoveWithEntity);
end
----------------------------------------------------------------------------------------
function AudioAreaRandom:UpdateFadeValue(player, fFade, fDistSq)
if (not(self.Properties.bEnabled) or (fFade == 0.0 and fDistSq == 0.0)) then
self.fFadeValue = 0.0;
self:_UpdateRtpc();
do return end;
end
if (self.Properties.fRtpcDistance > 0.0) then
if (self.nState == 2) then
if (self.fFadeValue ~= fFade) then
self.fFadeValue = math.abs(fFade);
self:_UpdateRtpc();
end
else
local fLocalFade = 1.0 - (math.sqrt(fDistSq) / self.Properties.fRtpcDistance);
self.fFadeValue = math.max(0, fLocalFade);
self:_UpdateRtpc();
end
end
end
----------------------------------------------------------------------------------------
AudioAreaRandom.Server = {
OnInit = function(self)
self:CliSrv_OnInit();
end,
OnShutDown = function(self)
end,
}
----------------------------------------------------------------------------------------
AudioAreaRandom.Client = {
OnInit = function(self)
self:RegisterForAreaEvents(1);
self:_LookupControlIDs();
self:_LookupObstructionSwitchIDs();
self:_SetObstruction();
self:CliSrv_OnInit();
end,
OnShutDown = function(self)
self:StopAll();
self.nState = 0;
self:RegisterForAreaEvents(0);
end,
OnHidden = function(self)
self:StopAll();
self.bIsHidden = true;
end,
OnUnHidden = function(self)
self.bIsHidden = false;
self:Play();
end,
OnAudioListenerEnterNearArea = function(self, player, nAreaID, fFade)
if (self.nState == 0) then
self.nState = 1;
self:Play();
self.fFadeValue = 0.0;
self:_UpdateRtpc();
end
end,
OnAudioListenerMoveNearArea = function(self, player, areaId, fFade, fDistsq)
self.nState = 1;
self:UpdateFadeValue(player, fFade, fDistsq);
end,
OnAudioListenerEnterArea = function(self, player, areaId, fFade)
if (self.nState == 0) then
-- possible if the listener is teleported or gets spawned inside the area
-- technically, the listener enters the Near Area and the Inside Area at the same time
self.nState = 2;
self:Play();
else
self.nState = 2;
end
self.fFadeValue = 1.0;
self:_UpdateRtpc();
end,
OnAudioListenerProceedFadeArea = function(self, player, areaId, fExternalFade)
-- fExternalFade holds the fade value which was calculated by an inner, higher priority area
-- in the AreaManager to fade out the outer sound dependent on the largest fade distance of all attached entities
if (fExternalFade > 0.0) then
self.nState = 2;
self:UpdateFadeValue(player, fExternalFade, 0.0);
else
self:UpdateFadeValue(player, 0.0, 0.0);
end
end,
OnAudioListenerLeaveArea = function(self, player, nAreaID, fFade)
self.nState = 1;
end,
OnAudioListenerLeaveNearArea = function(self, player, nAreaID, fFade)
self:Stop();
self.nState = 0;
self.fFadeValue = 0.0;
self:_UpdateRtpc();
end,
OnUnBindThis = function(self)
self.nState = 0;
end,
OnTimer = function(self, timerid, msec)
if (timerid == 0) then
self:Play();
end
end,
OnMove = function(self)
self.bHasMoved = true;
end,
}
----------------------------------------------------------------------------------------
-- Event Handlers
----------------------------------------------------------------------------------------
function AudioAreaRandom:Event_Enable(sender)
self.Properties.bEnabled = true;
self:OnPropertyChange();
end
function AudioAreaRandom:Event_Disable(sender)
self.Properties.bEnabled = false;
self:OnPropertyChange();
end
AudioAreaRandom.FlowEvents =
{
Inputs =
{
Enable = { AudioAreaRandom.Event_Enable, "bool" },
Disable = { AudioAreaRandom.Event_Disable, "bool" },
},
}
@@ -0,0 +1,334 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
Script.ReloadScript("scripts/Entities/Sound/Shared/AudioUtils.lua");
AudioTriggerSpot = {
type = "AudioTriggerSpot",
Editor = {
Model = "Editor/Objects/Sound.cgf",
Icon = "Sound.bmp",
},
Properties = {
bEnabled = true,
audioTriggerPlayTriggerName = "",
audioTriggerStopTriggerName = "",
bSerializePlayState = true, -- Determines if execution after de-serialization is needed.
eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_IGNORE,
bPlayOnX = false,
bPlayOnY = false,
bPlayOnZ = false,
fRadiusRandom = 10.0,
bPlayRandom = false,
fMinDelay = 1,
fMaxDelay = 2,
},
hOnTriggerID = nil,
hOffTriggerID = nil,
hCurrentOnTriggerID = nil,
hCurrentOffTriggerID = nil, -- only used in OnPropertyChange()
tObstructionType = {},
bIsHidden = false,
bIsPlaying = false,
bHasMoved = false,
bOriginalEnabled = true,
}
----------------------------------------------------------------------------------------
function AudioTriggerSpot:_LookupTriggerIDs()
self.hOnTriggerID = AudioUtils.LookupTriggerID(self.Properties.audioTriggerPlayTriggerName);
self.hOffTriggerID = AudioUtils.LookupTriggerID(self.Properties.audioTriggerStopTriggerName);
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:_LookupObstructionSwitchIDs()
-- cache the obstruction switch and state IDs
self.tObstructionType = AudioUtils.LookupObstructionSwitchAndStates();
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:_SetObstruction()
local nStateIdx = self.Properties.eiSoundObstructionType + 1;
self:SetAudioObstructionCalcType(self.Properties.eiSoundObstructionType, self:GetDefaultAuxAudioProxyID());
if ((self.tObstructionType.hSwitchID ~= nil) and (self.tObstructionType.tStateIDs[nStateIdx] ~= nil)) then
self:SetAudioSwitchState(self.tObstructionType.hSwitchID, self.tObstructionType.tStateIDs[nStateIdx], self:GetDefaultAuxAudioProxyID());
end
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:_GenerateOffset()
local offset = {x=0,y=0,z=0}
local len = 0
if (self.Properties.bPlayOnX) then
offset.x=randomF(-1,1);
end
if (self.Properties.bPlayOnY) then
offset.y=randomF(-1,1);
end
if (self.Properties.bPlayOnZ) then
offset.z=randomF(-1,1);
end
NormalizeVector(offset);
ScaleVectorInPlace(offset, randomF(0,self.Properties.fRadiusRandom));
return offset;
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:OnSpawn()
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY, 0);
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:OnSave(save)
save.Properties = self.Properties;
save.bIsPlaying = self.bIsPlaying;
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:OnLoad(load)
self.Properties = load.Properties;
self.bIsPlaying = load.bIsPlaying;
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:OnPostLoad()
self:_SetObstruction();
self:SetCurrentAudioEnvironments();
if (self.bIsPlaying and self.Properties.bSerializePlayState) then
self.bIsPlaying = false;
self:Play();
else
self.bIsPlaying = false;
end
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:_Init()
self.bIsPlaying = false;
self:SetAudioProxyOffset(g_Vectors.v000, self:GetDefaultAuxAudioProxyID());
self:NetPresent(0);
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:OnPropertyChange()
if (self.Properties.eiSoundObstructionType < AUDIO_OBSTRUCTION_TYPE_IGNORE) then
self.Properties.eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_IGNORE;
elseif (self.Properties.eiSoundObstructionType > AUDIO_OBSTRUCTION_TYPE_MULTI) then
self.Properties.eiSoundObstructionType = AUDIO_OBSTRUCTION_TYPE_MULTI;
end
self:_LookupTriggerIDs();
self:_SetObstruction();
self:SetCurrentAudioEnvironments();
self:SetAudioProxyOffset(g_Vectors.v000, self:GetDefaultAuxAudioProxyID());
if ((self.bIsPlaying) and (self.hCurrentOnTriggerID ~= self.hOnTriggerID)) then
-- Stop a possibly playing instance if the on-trigger changed!
self:StopAudioTrigger(self.hCurrentOnTriggerID, self:GetDefaultAuxAudioProxyID());
self.hCurrentOnTriggerID = self.hOnTriggerID;
self.bIsPlaying = false;
self.bHasMoved = false;
self:KillTimer(0);
end
if (not self.bIsPlaying) then
-- Try to play, if disabled, hidden or invalid on-trigger Play() will fail!
self:Play();
end
if (not self.Properties.bEnabled and ((self.bOriginalEnabled) or (self.hCurrentOffTriggerID ~= self.hOffTriggerID))) then
self.hCurrentOffTriggerID = self.hOffTriggerID;
self:Stop(); -- stop if disabled, either stops running StartTrigger or executes StopTrigger!
end
self.bOriginalEnabled = self.Properties.bEnabled;
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:OnReset(bToGame)
if (bToGame) then
-- store the entity's "bEnabled" property's value so we can adjust back to it if changed over the course of the game
self.bOriginalEnabled = self.Properties.bEnabled;
-- re-execute this ATS once upon entering game mode
self:Stop();
self:Play();
else
self.Properties.bEnabled = self.bOriginalEnabled;
end
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:OnTransformFromEditorDone()
self:SetCurrentAudioEnvironments();
end
----------------------------------------------------------------------------------------
AudioTriggerSpot["Server"] = {
OnInit = function (self)
self:_Init();
end,
OnShutDown = function (self)
end,
}
----------------------------------------------------------------------------------------
AudioTriggerSpot["Client"] = {
----------------------------------------------------------------------------------------
OnInit = function(self)
self:_Init();
self:_LookupTriggerIDs();
self:_LookupObstructionSwitchIDs();
self:_SetObstruction();
self:SetCurrentAudioEnvironments();
self:Play();
end,
----------------------------------------------------------------------------------------
OnShutDown = function(self)
self:StopAll();
end,
----------------------------------------------------------------------------------------
OnSoundDone = function(self, hTriggerID)
if (self.hOnTriggerID == hTriggerID) then
self:ActivateOutput("Done", true);
end
end,
----------------------------------------------------------------------------------------
OnTimer = function(self, timerid, msec)
if (timerid == 0) then
self:Play();
end
end,
----------------------------------------------------------------------------------------
OnHidden = function(self)
self:StopAll();
self.bIsHidden = true;
end,
----------------------------------------------------------------------------------------
OnUnHidden = function(self)
self.bIsHidden = false;
self:Play();
end,
----------------------------------------------------------------------------------------
OnMove = function(self)
self.bHasMoved = true;
end,
}
----------------------------------------------------------------------------------------
function AudioTriggerSpot:Play()
if ((self.hOnTriggerID ~= nil) and (self.Properties.bEnabled) and (not self.bIsHidden)) then
local offset = self:_GenerateOffset();
if (LengthSqVector(offset) > 0.00001) then -- offset is longer than 1cm
self:SetAudioProxyOffset(offset, self:GetDefaultAuxAudioProxyID());
self:SetCurrentAudioEnvironments();
elseif (self.bHasMoved) then
self:SetCurrentAudioEnvironments();
end
self:ExecuteAudioTrigger(self.hOnTriggerID, self:GetDefaultAuxAudioProxyID());
self.bIsPlaying = true;
self.bHasMoved = false;
self.hCurrentOnTriggerID = self.hOnTriggerID;
if (self.Properties.bPlayRandom) then
self:SetTimer(0, 1000 * randomF(self.Properties.fMinDelay, self.Properties.fMaxDelay));
end
end
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:Stop()
if (not self.bIsHidden) then
-- Cannot check against "self.bIsPlaying" otherwise we won't execute the StopTrigger if there's no StartTrigger set!
if (self.hOffTriggerID ~= nil) then
local offset = self:_GenerateOffset();
if (LengthSqVector(offset) > 0.00001) then-- offset is longer than 1cm
self:SetAudioProxyOffset(offset, self:GetDefaultAuxAudioProxyID());
self:SetCurrentAudioEnvironments();
elseif (self.bHasMoved) then
self:SetCurrentAudioEnvironments();
end
self:ExecuteAudioTrigger(self.hOffTriggerID, self:GetDefaultAuxAudioProxyID());
elseif (self.hOnTriggerID ~= nil) then
self:StopAudioTrigger(self.hOnTriggerID, self:GetDefaultAuxAudioProxyID());
end
end
self.bIsPlaying = false;
self.bHasMoved = false;
self:KillTimer(0);
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:StopAll()
if (self.hOnTriggerID ~= nil) then
self:StopAudioTrigger(self.hOnTriggerID, self:GetDefaultAuxAudioProxyID());
end
if (self.hOffTriggerID ~= nil) then
self:StopAudioTrigger(self.hOffTriggerID, self:GetDefaultAuxAudioProxyID());
end
self.bIsPlaying = false;
self:KillTimer(0);
end
------------------------------------------------------------------------------------------------------
-- Event Handlers
------------------------------------------------------------------------------------------------------
function AudioTriggerSpot:Event_Enable(sender)
if (not self.Properties.bEnabled) then
self.Properties.bEnabled = true;
self:Play();
end
--BroadcastEvent(self, "Enable");
end
----------------------------------------------------------------------------------------
function AudioTriggerSpot:Event_Disable(sender)
self:Stop();
self.Properties.bEnabled = false;
--BroadcastEvent(self, "Disable");
end
----------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------
AudioTriggerSpot.FlowEvents =
{
Inputs =
{
Enable = { AudioTriggerSpot.Event_Enable, "bool" },
Disable = { AudioTriggerSpot.Event_Disable, "bool" },
},
Outputs =
{
Done = "bool",
},
}
@@ -0,0 +1,83 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
--
----------------------------------------------------------------------------------------------------
AudioUtils = {
-- these names should exactly match those defined in ATLEntities.cpp and in libs/gameaudio/wwise/default_controls.xml
sObstructionCalcSwitchName = "ObstructionOcclusionCalculationType",
sObstructionStateNames = {"Ignore", "SingleRay", "MultiRay"},
}
----------------------------------------------------------------------------------------
function AudioUtils.LookupTriggerID(sTriggerName)
local hTriggerID = nil;
if ((sTriggerName ~= nil) and (sTriggerName ~= "")) then
hTriggerID = Sound.GetAudioTriggerID(sTriggerName);
end
return hTriggerID;
end
----------------------------------------------------------------------------------------
function AudioUtils.LookupRtpcID(sRtpcName)
local hRtpcID = nil;
if ((sRtpcName ~= nil) and (sRtpcName ~= "")) then
hRtpcID = Sound.GetAudioRtpcID(sRtpcName);
end
return hRtpcID;
end
----------------------------------------------------------------------------------------
function AudioUtils.LookupSwitchID(sSwitchName)
local hSwitchID = nil;
if ((sSwitchName ~= nil) and (sSwitchName ~= "")) then
hSwitchID = Sound.GetAudioSwitchID(sSwitchName);
end
return hSwitchID;
end
----------------------------------------------------------------------------------------
function AudioUtils.LookupSwitchStateIDs(hSwitchID, tStateNames)
local tStateIDs = {};
if ((hSwitchID ~= nil) and (tStateNames ~= nil)) then
for i, name in ipairs(tStateNames) do
tStateIDs[i] = Sound.GetAudioSwitchStateID(hSwitchID, name);
end
end
return tStateIDs;
end
----------------------------------------------------------------------------------------
function AudioUtils.LookupAudioEnvironmentID(sEnvironmentName)
local hEnvironmentID = nil;
if ((sEnvironmentName ~= nil) and (sEnvironmentName ~= "")) then
hEnvironmentID = Sound.GetAudioEnvironmentID(sEnvironmentName);
end
return hEnvironmentID;
end
----------------------------------------------------------------------------------------
function AudioUtils.LookupObstructionSwitchAndStates()
local nSwitch = AudioUtils.LookupSwitchID(AudioUtils.sObstructionCalcSwitchName);
local tStates = AudioUtils.LookupSwitchStateIDs(nSwitch, AudioUtils.sObstructionStateNames);
return {hSwitchID = nSwitch, tStateIDs = tStates};
end
@@ -0,0 +1,362 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
-- Original file Copyright Crytek GMBH or its affiliates, used under license.
--
--
-- Description: Network-ready Area Trigger
--
----------------------------------------------------------------------------------------------------
AreaTrigger =
{
Properties =
{
bEnabled = 1,
bTriggerOnce = 0,
bOnlyPlayers = 1,
bOnlyLocalPlayer= 0,
esFactionFilter = "",
ScriptCommand = "",
PlaySequence = "",
bInVehicleOnly = 0,
MultiplayerOptions =
{
bNetworked = 0,
bPerPlayer = 0,
},
},
Client = {},
Server = {},
Editor =
{
Model = "Editor/Objects/T.cgf",
Icon = "AreaTrigger.bmp",
IsScalable = false;
IsRotatable = false;
},
}
Net.Expose
{
Class = AreaTrigger,
ClientMethods =
{
ClEnter = { RELIABLE_ORDERED, PRE_ATTACH, ENTITYID, INT8 },
ClLeave = { RELIABLE_ORDERED, PRE_ATTACH, ENTITYID, INT8 },
},
ServerMethods = {},
ServerProperties = {}
}
function AreaTrigger:OnPropertyChange()
self:OnReset();
end
function AreaTrigger:OnReset()
self.enabled = nil;
self.triggerOnce = tonumber(self.Properties.bTriggerOnce)~=0;
self.localOnly = self.Properties.MultiplayerOptions.bNetworked==0;
self.perPlayer = tonumber(self.Properties.MultiplayerOptions.bPerPlayer)~=0;
self.isServer=CryAction.IsServer();
self.isClient=CryAction.IsClient();
self.inside={};
self.insideCount=0;
if (not self.localOnly) then
self.triggeredPP={};
self.triggeredOncePP={};
else
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
self.triggeredOnce=nil;
self.triggered=nil;
self:Enable(tonumber(self.Properties.bEnabled)~=0);
self:ActivateOutput("NrOfEntitiesInside", 0);
end
function AreaTrigger:Enable(enable)
self.enabled=enable;
self:RegisterForAreaEvents(enable and 1 or 0);
end
function AreaTrigger:OnSpawn()
self:OnReset();
end
function AreaTrigger:OnSave(props)
props.enabled = self.enabled;
props.triggered = self.triggered;
props.triggeredOnce = self.triggeredOnce;
end
function AreaTrigger:OnLoad(props)
self:OnReset();
self.enabled = props.enabled;
self.triggered = props.triggered;
self.triggeredOnce = props.triggeredOnce;
end
function AreaTrigger:CanTrigger(entityId)
local entity=System.GetEntity(entityId);
if (not entity) then return; end;
local Properties = self.Properties;
local isAPlayer = ActorSystem.IsPlayer(entity.id);
if (Properties.bOnlyPlayers ~= 0 and not(isAPlayer)) then
return false;
end
if (Properties.bOnlyLocalPlayer ~= 0 and entity ~= g_localActor) then
return false;
end
if (Properties.bInVehicleOnly ~= 0 and not entity.vehicleId) then
return false;
end
if (Properties.esFactionFilter ~= "") then
local faction = AI.GetFactionOf(entity.id) or "";
if (faction ~= Properties.esFactionFilter) then
return false
end
end
return true;
end
function AreaTrigger:Trigger(entityId, enter)
self:ActivateOutput("NrOfEntitiesInside", self.insideCount);
self:ActivateOutput("Sender", entityId or NULL_ENTITY);
self:ActivateOutput("Faction", AI.GetFactionOf(entityId or NULL_ENTITY) or "");
if (enter) then
if(self.Properties.ScriptCommand and self.Properties.ScriptCommand~="")then
local f = loadstring(self.Properties.ScriptCommand);
if (f~=nil) then
f();
end
end
if(self.Properties.PlaySequence~="")then
Movie.PlaySequence(self.Properties.PlaySequence);
end
end
end
function AreaTrigger:EnteredArea(entity, areaId)
if (not self:CanTrigger(entity.id, areaId)) then
return;
end
self.inside[entity.id]=true;
self.insideCount=self.insideCount+1;
self:Event_Enter(entity.id);
end
function AreaTrigger:LeftArea(entity, areaId)
if (not self:CanTrigger(entity.id, areaId)) then
return;
end
self.inside[entity.id]=nil;
self.insideCount=self.insideCount-1;
self:Event_Leave(entity.id);
end
function AreaTrigger.Server:OnEnterArea(entity, areaId)
if (self:CanTrigger(entity.id)) then
self:EnteredArea(entity, areaId);
end
end
function AreaTrigger.Server:OnLeaveArea(entity, areaId)
self:LeftArea(entity, areaId);
end
function AreaTrigger.Client:OnEnterArea(entity, areaId)
if (not self:CanTrigger(entity.id)) then return; end;
if (not self.localOnly or self.isServer) then return; end;
self:EnteredArea(entity, areaId);
end
function AreaTrigger.Client:OnLeaveArea(entity, areaId)
if (not self.localOnly or self.isServer) then return; end;
self:LeftArea(entity, areaId);
end
function AreaTrigger:Event_Enter(entityId)
if (not self.enabled) then return; end; -- TODO: might need a self.active here
if (self.triggerOnce) then
if (self.localOnly) then
if (self.triggeredOnce) then
return;
end
elseif (self.perPlayer and self.triggeredOncePP[entityId]) then -- TODO: will need to skip this for non-player entities
return;
elseif (not self.perPlayer and self.triggeredOnce) then
return;
end
end
self.triggered=true;
self.triggeredOnce=true;
if (not self.localOnly and entityId) then
self.triggeredPP[entityId]=true;
self.triggeredOncePP[entityId]=true;
end
self:Trigger(entityId, true);
--BroadcastEvent(self, "Enter");
self:ActivateOutput("Enter", entityId);
if (not self.localOnly and self.isServer) then
if (self.isClient) then
self.otherClients:ClEnter(g_localChannelId, entityId or NULL_ENTITY, self.insideCount);
else
self.allClients:ClEnter(entityId or NULL_ENTITY, self.insideCount);
end
end
end
function AreaTrigger:Event_Leave(entityId)
if (not self.enabled) then return; end;
if (self.localOnly and not self.triggered) then return; end;
if (self.perPlayer) then
if (not self.localOnly and entityId) then
if (not self.triggeredPP[entityId]) then return; end;
end
else
if (not self.triggered) then return; end;
end
--only disable triggered when all players are gone
if(self.insideCount == 0) then
self.triggered=nil;
end
if (not self.localOnly and entityId and self.insideCount == 0) then
self.triggeredPP[entityId]=nil;
end
self:Trigger(entityId, false);
--BroadcastEvent(self, "Leave");
self:ActivateOutput("Leave", entityId or NULL_ENTITY);
if (not self.localOnly and self.isServer) then
if (self.isClient) then
self.otherClients:ClLeave(g_localChannelId, entityId or NULL_ENTITY, self.insideCount);
else
self.allClients:ClLeave(entityId or NULL_ENTITY, self.insideCount);
end
end
end
function AreaTrigger.Client:ClEnter(entityId, insideCount)
self.insideCount = insideCount;
self.inside[entityId] = true;
self:Trigger(entityId, true);
--BroadcastEvent(self, "Enter");
self:ActivateOutput("Enter", entityId);
end
function AreaTrigger.Client:ClLeave(entityId, inside)
self.insideCount = inside;
self.inside[entityId] = nil;
self:Trigger(entityId, false);
self:ActivateOutput("Sender", entityId);
self:ActivateOutput("NrOfEntitiesInside", inside);
--BroadcastEvent(self, "Leave");
self:ActivateOutput("Leave", entityId);
end
function AreaTrigger:Event_Enable()
self:Enable(true);
local entityIdInside = next(self.inside);
if (entityIdInside) then
self:Event_Enter( entityIdInside );
end;
self:ActivateOutput("NrOfEntitiesInside", self.insideCount);
BroadcastEvent(self, "Enable");
end
function AreaTrigger:Event_Disable()
self:Enable(false);
BroadcastEvent(self, "Disable");
end
AreaTrigger.FlowEvents =
{
Inputs =
{
Disable = { AreaTrigger.Event_Disable, "bool" },
Enable = { AreaTrigger.Event_Enable, "bool" },
Enter = { AreaTrigger.Event_Enter, "bool" },
Leave = { AreaTrigger.Event_Leave, "bool" },
},
Outputs =
{
Disable = "bool",
Enable = "bool",
Enter = "entity",
Leave = "entity",
NrOfEntitiesInside = "int",
Sender = "entity",
Faction = "string",
},
}
@@ -0,0 +1,620 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
-- Original file Copyright Crytek GMBH or its affiliates, used under license.
--
--
-- Description: Network-ready Proximity Trigger
--
----------------------------------------------------------------------------------------------------
ProximityTrigger =
{
Properties =
{
DimX = 5,
DimY = 5,
DimZ = 5,
bEnabled = 1,
EnterDelay = 0,
ExitDelay = 0,
bOnlyPlayer = 1,
bOnlyMyPlayer = 0,
bOnlyAI = 0,
bOnlySpecialAI = 0,
esFactionFilter = "",
OnlySelectedEntity = "None",
bRemoveOnTrigger = 0,
bTriggerOnce = 0,
ScriptCommand = "",
PlaySequence = "",
bInVehicleOnly = 0,
bOnlyOneEntity = 0,
UsableMessage = "",
bActivateWithUseButton = 0,
MultiplayerOptions =
{
bNetworked = 0,
bPerPlayer = 0,
},
},
Client={},
Server={},
Editor =
{
Model="Editor/Objects/T.cgf",
Icon="Trigger.bmp",
ShowBounds = 1,
IsScalable = false;
IsRotatable = false;
},
}
Net.Expose
{
Class = ProximityTrigger,
ClientMethods =
{
ClEnter = { RELIABLE_ORDERED, PRE_ATTACH, ENTITYID, INT8},
ClLeave = { RELIABLE_ORDERED, PRE_ATTACH, ENTITYID, INT8},
},
ServerMethods =
{
SvRequestUse = { RELIABLE_ORDERED, PRE_ATTACH, ENTITYID },
},
ServerProperties = {}
}
function ProximityTrigger:OnPropertyChange()
self:OnReset();
end
function ProximityTrigger:OnReset()
-- Precalcs some CVars used to test triggering entities based in their names. ("selectedEntity" is a misleading name for all this)
self.bUsesExactSelectedEntity = false;
self.bUsesWildcardSelectedEntity = false;
if (self.Properties.OnlySelectedEntity~="None" and self.Properties.OnlySelectedEntity~="") then
local indexChar = string.find( self.Properties.OnlySelectedEntity, "*" );
if (indexChar and indexChar>1) then
if (indexChar<5) then
LogWarning( "proximity trigger: '%s' is using a too much generic name for 'selectedEntity' field", self:GetName() );
end
self.bUsesWildcardSelectedEntity = true;
self.stringRootSelectedEntity = string.sub( self.Properties.OnlySelectedEntity, 1, indexChar - 1 );
else
self.bUsesExactSelectedEntity = true;
end
end
if (self.timers) then
for i,v in pairs(self.timers) do
self:KillTimer(i);
end
end
self.timerId = 0;
self.enabled = nil;
self.usable = tonumber(self.Properties.bActivateWithUseButton)~=0;
self.triggerOnce = tonumber(self.Properties.bTriggerOnce)~=0;
self.localOnly = self.Properties.MultiplayerOptions.bNetworked==0;
self.perPlayer = tonumber(self.Properties.MultiplayerOptions.bPerPlayer)~=0;
self.isServer=CryAction.IsServer();
self.isClient=CryAction.IsClient();
self.inside={};
self.timers={};
if (not self.localOnly) then
self.triggeredPP={};
self.triggeredOncePP={};
else
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
end
self.triggeredOnce=nil;
self.triggered=nil;
self.insideCount=0;
local min = { x=-self.Properties.DimX/2, y=-self.Properties.DimY/2, z=-self.Properties.DimZ/2 };
local max = { x=self.Properties.DimX/2, y=self.Properties.DimY/2, z=self.Properties.DimZ/2 };
self:SetUpdatePolicy( ENTITY_UPDATE_PHYSICS );
self:SetTriggerBBox( min, max );
self:Enable(tonumber(self.Properties.bEnabled)~=0);
self:InvalidateTrigger();
self:ActivateOutput("NrOfEntitiesInside", 0);
end
function ProximityTrigger:Enable(enable)
self.enabled=enable;
self:RegisterForAreaEvents(enable and 1 or 0);
end
function ProximityTrigger:OnSpawn()
self:OnReset();
end
function ProximityTrigger:OnDestroy()
end
function ProximityTrigger:OnSave(tbl)
tbl.enabled = self.enabled;
tbl.triggered = self.triggered;
tbl.triggeredOnce = self.triggeredOnce;
end
function ProximityTrigger:OnLoad(tbl)
self:OnReset();
self.enabled = tbl.enabled;
self.triggered = tbl.triggered;
self.triggeredOnce = tbl.triggeredOnce;
end
function ProximityTrigger:Event_Enter(entityId)
if (not self.enabled) then return; end; -- TODO: might need a self.active here
if (self.triggerOnce) then
if (self.localOnly) then
if (self.triggeredOnce) then
return;
end
elseif (self.perPlayer and self.triggeredOncePP[entityId]) then -- TODO: will need to skip this for non-player entities
return;
elseif (not self.perPlayer and self.triggeredOnce) then
return;
end
end
self.triggered=true;
self.triggeredOnce=true;
if (not self.localOnly and entityId) then
self.triggeredPP[entityId]=true;
self.triggeredOncePP[entityId]=true;
end
-- Log(" ProximityTrigger: %s:Event_Enter(%s) inside: %d", self:GetName(), EntityName(entityId), self.insideCount);
self:Trigger(entityId, self.insideCount);
--BroadcastEvent(self, "Enter");
self:ActivateOutput("Enter", entityId or NULL_ENTITY);
if (not self.localOnly and self.isServer) then
self.otherClients:ClEnter(g_localChannelId, entityId or NULL_ENTITY, self.insideCount);
end
end
function ProximityTrigger.Client:ClEnter(entityId, insideCount)
-- Log("ProximityTrigger: %s.Client:ClEnter(%s) count: %d", self:GetName(), EntityName(entityId), insideCount);
self:Trigger(entityId, insideCount);
--BroadcastEvent(self, "Enter");
self:ActivateOutput("Enter", entityId);
end
function ProximityTrigger:Event_Leave(entityId)
if (not self.enabled) then return; end;
if (self.localOnly and not self.triggered) then return; end;
if (self.perPlayer) then
if (not self.localOnly and entityId) then
if (not self.triggeredPP[entityId]) then
return;
end;
end
else
if (not self.triggered) then
return;
end;
end
--only disable triggered when all players are gone
if(self.insideCount == 0) then
self.triggered=nil;
end
if (not self.localOnly and entityId and self.insideCount == 0) then
self.triggeredPP[entityId]=nil;
end
--Log("%s:Event_Leave(%s)", self:GetName(), EntityName(entityId));
self:ActivateOutput("Sender", entityId or NULL_ENTITY);
self:ActivateOutput("NrOfEntitiesInside", self.insideCount);
--BroadcastEvent(self, "Leave");
self:ActivateOutput("Leave", entityId or NULL_ENTITY);
if (not self.localOnly and self.isServer) then
self.otherClients:ClLeave(g_localChannelId, entityId or NULL_ENTITY, self.insideCount);
end
end
function ProximityTrigger.Client:ClLeave(entityId, inside)
-- Log("%s.Client:ClLeave(%s, %s)", self:GetName(), EntityName(entityId), tostring(inside));
self:ActivateOutput("Sender", entityId);
self:ActivateOutput("NrOfEntitiesInside", inside);
self:ActivateOutput("Leave", entityId);
--BroadcastEvent(self, "Leave");
end
function ProximityTrigger:Event_Enable()
if (self.enabled) then return; end;
-- Act as if everyone entered the trigger
self.enabled = true;
for k,v in pairs(self.inside) do
self:Event_Enter( k );
end;
self:ActivateOutput("NrOfEntitiesInside", self.insideCount);
BroadcastEvent(self, "Enable");
end
function ProximityTrigger:Event_Disable()
if (not self.enabled) then return; end;
-- Act as if everyone left the trigger
self.enabled = false;
for k,v in pairs(self.inside) do
self:Event_Leave( k );
end;
self:ActivateOutput("NrOfEntitiesInside", 0);
BroadcastEvent(self, "Disable");
end
function ProximityTrigger:CreateTimer(entityId, time, leave)
local timerId=self.timerId;
if (timerId>1023) then
timerId=0;
end
timerId=timerId+1;
self.timerId=timerId;
if (leave) then
timerId=timerId+1024;
end
self.timers[timerId]=entityId;
self:SetTimer(timerId, time);
end
function ProximityTrigger.Client:OnTimer(timerId, msec)
if (self.localOnly and not self.isServer) then
self:OnTimer(timerId, msec);
end
end
function ProximityTrigger.Server:OnTimer(timerId, msec)
self:OnTimer(timerId, msec);
end
function ProximityTrigger:OnTimer(timerId, msec)
if (timerId==2048) then
self:CheckAIDeaths()
return;
end
local entityId=self.timers[timerId];
if (not entityId) then return; end;
if (timerId>1023) then
self:Event_Leave(entityId);
else
self:Event_Enter(entityId);
end
end
function ProximityTrigger:CheckAIDeaths()
local amountInside = 0;
for k,v in pairs(self.inside) do
local entity = System.GetEntity( k );
if (entity~=nil and entity.ai~=nil and entity.lastHealth<=0) then
self.inside[k] = nil;
else
amountInside = amountInside + 1;
end
end
if (amountInside~=self.insideCount) then
self.insideCount = amountInside;
if (self.enabled) then
self:ActivateOutput("NrOfEntitiesInside", self.insideCount);
end
end
if (amountInside~=0) then
self:CreateAIDeathsCheckTrigger();
else
self.timers[2048]=false; --to know that we are not using the AI trigger now
end
end
-- this timer should be created only when it is a trigger that reacts to AI (which should be only a few), and there are AIs inside
function ProximityTrigger:CreateAIDeathsCheckTrigger()
self.timers[2048]=true; -- to know that we are using the AI timer. 2048 is the AI timer id
self:SetTimer( 2048, 3000);
end
function ProximityTrigger.Server:SvRequestUse(userId)
local entity=System.GetEntity(userId);
if (entity) then
self:OnUsed(entity);
end
end
function ProximityTrigger:OnUsed(user)
if (not self:CanTrigger(user)) then return; end;
Log("%s:OnUsed(%s)", self:GetName(), EntityName(user));
self:LockUsability();
if (self.localOnly or self.isServer) then
self:CreateTimer(user.id, self.Properties.EnterDelay*1000);
else
self.server:SvRequestUse(user.id);
end
end
function ProximityTrigger:Trigger(entityId, inside)
if (self.enabled) then
self:ActivateOutput("NrOfEntitiesInside", inside);
end
if(self.Properties.ScriptCommand and self.Properties.ScriptCommand~="")then
local f = loadstring(self.Properties.ScriptCommand);
if (f~=nil) then
f();
end
end
if(self.Properties.PlaySequence~="")then
Movie.PlaySequence(self.Properties.PlaySequence);
end
self:ActivateOutput("Sender", entityId or NULL_ENTITY);
if(AI ~= nil) then
self:ActivateOutput("Faction", AI.GetFactionOf(entityId or NULL_ENTITY) or "");
end
local isAPlayer = ActorSystem.IsPlayer(entityId);
if self.Properties.bRemoveOnTrigger ~= 0 and not isAPlayer then
System.RemoveEntity(entityId);
end
end
function ProximityTrigger:EnteredArea(entity, areaId)
if (not self:CanTrigger(entity, areaId)) then
return;
end
if (tonumber(self.Properties.bOnlyOneEntity)~=0 and self.insideCount>0) then
return;
end
self.inside[entity.id]=true;
self.insideCount=self.insideCount+1;
if (not entity.ai) then
if (self.Properties.bActivateWithUseButton~=0) then
return;
end
end
if (not self.enabled) then return; end;
self:CreateTimer(entity.id, self.Properties.EnterDelay*1000);
if (entity.ai and self.timers[2048]~=true) then -- 2048 is the special timer id used to check the deaths of AIs
self:CreateAIDeathsCheckTrigger();
end
end
function ProximityTrigger:LeftArea(entity, areaId)
if (not self:CanTrigger(entity, areaId)) then
return;
end
self.inside[entity.id]=nil;
self.insideCount=self.insideCount-1;
if(self.Properties.ExitDelay==0) then
self.Properties.ExitDelay=0.01;
end
if (not self.enabled) then return; end;
self:CreateTimer(entity.id, self.Properties.ExitDelay*1000, true);
end
function ProximityTrigger.Server:OnEnterArea(entity, areaId)
if (self:CanTrigger(entity)) then
self:EnteredArea(entity, areaId);
end
end
function ProximityTrigger.Server:OnLeaveArea(entity, areaId)
self:LeftArea(entity, areaId);
end
function ProximityTrigger.Client:OnEnterArea(entity, areaId)
if (not self:CanTrigger(entity)) then return; end;
if (entity.actor) then
if (self.usable and self.enabled) then
self:LockUsability(true);
end
end
if (not self.localOnly or self.isServer) then return; end;
self:EnteredArea(entity, areaId);
end
function ProximityTrigger.Client:OnLeaveArea(entity, areaId)
if (entity.actor) then
if (self.usable and self.enabled) then
self:LockUsability(true);
end
end
if (not self.localOnly or self.isServer) then return; end;
self:LeftArea(entity, areaId);
end
function ProximityTrigger:CanTrigger(entity)
local Properties = self.Properties;
if (entity.ai and entity.lastHealth and (entity.lastHealth <= 0)) then
return false;
end
local isAPlayer = ActorSystem.IsPlayer(entity.id);
if (Properties.bOnlyPlayer ~= 0 and not(isAPlayer)) then
return false;
end
if (Properties.bOnlySpecialAI ~= 0 and entity.ai and entity.Properties.special==0) then
return false;
end
if (Properties.bOnlyAI ~=0 and not entity.ai) then
return false;
end
if (Properties.bOnlyMyPlayer ~= 0 and entity ~= g_localActor) then
return false;
end
if (Properties.bInVehicleOnly ~= 0 and not entity.vehicleId) then
return false;
end
-- looks for exact name match, if defined
if (self.bUsesExactSelectedEntity and entity:GetName()~=Properties.OnlySelectedEntity) then
return false;
end
-- looks for generic (wildcard) name match, if defined
if (self.bUsesWildcardSelectedEntity) then
local indexStringFound = string.find( entity:GetName(), self.stringRootSelectedEntity );
if (indexStringFound~=1) then
return false;
end
end
if (Properties.esFactionFilter ~= "") then
local faction = AI.GetFactionOf(entity.id) or "";
if (faction ~= Properties.esFactionFilter) then
return false
end
end
return true;
end
function ProximityTrigger:IsUsable(user)
return self.usable and self.enabled;
end
function ProximityTrigger:LockUsability(lock)
local player=g_localActor;
if (player) then
if (lock) then
player.actor:SetExtensionParams("Interactor", {locker = self.id, lockId = self.id, lockIdx = 1});
else
player.actor:SetExtensionParams("Interactor", {locker = self.id, lockId = NULL_ENTITY, lockIdx = 0});
end
end
end
function ProximityTrigger:GetUsableMessage()
return self.Properties.UsableMessage or "";
end
ProximityTrigger.FlowEvents =
{
Inputs =
{
Disable = { ProximityTrigger.Event_Disable, "bool" },
Enable = { ProximityTrigger.Event_Enable, "bool" },
Enter = { ProximityTrigger.Event_Enter, "bool" },
Leave = { ProximityTrigger.Event_Leave, "bool" },
},
Outputs =
{
NrOfEntitiesInside = "int",
Disable = "bool",
Enable = "bool",
Enter = "entity",
Leave = "entity",
Sender = "entity",
Faction = "string",
},
}
@@ -0,0 +1,32 @@
----------------------------------------------------------------------------------------------------
--
-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-- its licensors.
--
-- For complete copyright and license terms please see the LICENSE at the root of this
-- distribution (the "License"). All use of this software is governed by the License,
-- or, if provided, by the license below or the license accompanying this file. Do not
-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--
-- Original file Copyright Crytek GMBH or its affiliates, used under license.
--
--
--
----------------------------------------------------------------------------------------------------
UiCanvasRefEntity =
{
canvasID = 0,
Properties =
{
fileCanvasPath = "",
},
Editor =
{
Icon = "UiCanvasRefEntity.bmp",
IconOnTop = 1,
},
}