Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
+299
View File
@@ -0,0 +1,299 @@
----------------------------------------------------------------------------------------------------
--
-- 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.
--
--
----------------------------------------------------------------------------------------------------
----------------------------------------------------
-- Common Globals and Definitions.
----------------------------------------------------
----------------------------------------------------
-- data structure passed to the Signals, use this global to avoid temporary lua mem allocation
g_SignalData_point = {x=0,y=0,z=0};
g_SignalData_point2 = {x=0,y=0,z=0};
-- REMEMBER! ALWAYS write
-- g_SignalData.point = g_SignalData_point
-- before doing direct value assignment (i.e. not referenced) like
-- g_SignalData.point.x = ...
-- and any math.lua vector function on it (FastSumVectors(g_SignalData.point,..) etc
g_SignalData = {
point = g_SignalData_point, -- since g_SignalData.point is always used as a handler
point2 = g_SignalData_point2,
ObjectName = "",
id = NULL_ENTITY,
fValue = 0,
iValue = 0,
iValue2 = 0,
}
g_StringTemp1 = " ";
g_HitTable = {{},{},{},{},{},{},{},{},{},{},}
function ShowTime()
local ttime=System.GetLocalOSTime();
System.Log(string.format("%d/%d/%d, %02d:%02d", ttime.mday, ttime.mon+1, ttime.year+1900, ttime.hour, ttime.min));
end
function count(_tbl)
local count = 0;
if (_tbl) then
for i,v in pairs(_tbl) do
count = count+1;
end
end
return count;
end
function new(_obj, norecurse)
if (type(_obj) == "table") then
local _newobj = {};
if (norecurse) then
for i,f in pairs(_obj) do
_newobj[i] = f;
end
else
for i,f in pairs(_obj) do
if ((type(f) == "table") and (_obj~=f)) then -- avoid recursing into itself
_newobj[i] = new(f);
else
_newobj[i] = f;
end
end
end
return _newobj;
else
return _obj;
end
end
function merge(dst, src, recurse)
for i,v in pairs(src) do
if (type(v) ~= "function") then
if(recurse) then
if((type(v) == "table") and (v ~= src))then -- avoid recursing into itself
if (dst[i] == nil) then
dst[i] = {};
end
merge(dst[i], v, recurse);
elseif (dst[i] == nil) then
dst[i] = v;
end
elseif (dst[i] == nil) then
dst[i] = v;
end
end
end
return dst;
end
function mergef(dst, src, recursive)
for i,v in pairs(src) do
if (recursive) then
if((type(v) == "table") and (v ~= src))then -- avoid recursing into itself
if (dst[i] == nil) then
dst[i] = {};
end
mergef(dst[i], v, recursive);
elseif (dst[i] == nil) then
dst[i] = v;
end
elseif (dst[i] == nil) then
dst[i] = v;
end
end
return dst;
end
function Vec2Str(vec)
return string.format("(x: %.3f y: %.3f z: %.3f)", vec.x, vec.y, vec.z);
end
function LogError(fmt, ...)
System.Log("$4"..string.format(fmt, ...));
end
function LogWarning(fmt, ...)
System.Log("$6"..string.format(fmt, ...));
end
function Log(fmt, ...)
System.Log(string.format(fmt, ...));
end
g_dump_tabs=0;
function dump(_class, no_func, depth)
if not _class then
System.Log("$2nil");
else
if (not depth) then
depth = 8;
end
local str="";
for n=0,g_dump_tabs,1 do
str=str.." ";
end
for i,field in pairs(_class) do
if(type(field)=="table") then
if (g_dump_tabs < depth) then
g_dump_tabs=g_dump_tabs+1;
System.Log(str.."$4"..tostring(i).."$1= {");
dump(field, no_func, depth);
System.Log(str.."$1}");
g_dump_tabs=g_dump_tabs-1;
else
System.Log(str.."$4"..tostring(i).."$1= { $4...$1 }");
end
else
if(type(field)=="number" ) then
System.Log("$2"..str.."$6"..tostring(i).."$1=$8"..field);
elseif(type(field) == "string") then
System.Log("$2"..str.."$6"..tostring(i).."$1=$8".."\""..field.."\"");
elseif(type(field) == "boolean") then
System.Log("$2"..str.."$6"..tostring(i).."$1=$8".."\""..tostring(field).."\"");
else
if(not no_func)then
if(type(field)=="function")then
System.Log("$2"..str.."$5"..tostring(i).."()");
else
System.Log("$2"..str.."$7"..tostring(i).."$8<userdata>");
end
end
end
end
end
end
end
-- check if a string is set and it's length > 0
function EmptyString(str)
if (str and string.len(str) > 0) then
return false;
end
return true;
end
-- check if a number value is true or false
-- usefull for entity parameters
function NumberToBool(n)
if (n and (tonumber(n) ~= 0)) then
return true;
else
return false;
end
end
-- easy way to log entity id
-- accepts both entity table or entityid
function EntityName(entity)
if (type(entity) == "userdata") then
local e = System.GetEntity(entity);
if (e) then
return e:GetName();
end
elseif (type(entity) == "table") then
return entity:GetName();
end
return "";
end
-- easy way to get entity by name
-- usefull for "console debugging"!
function EntityNamed(name)
return System.GetEntityByName(name);
end
function SafeTableGet( table, name )
if table then return table[name] else return nil end
end
----------------------------------------------------
-- Load commonly used globals.
----------------------------------------------------
Script.ReloadScript("scripts/Utils/Containers.lua");
Script.ReloadScript("scripts/Utils/Math.lua");
Script.ReloadScript("scripts/Utils/EntityUtils.lua");
----------------------------------------------------
g_AIDebugToggleOn=0;
--///////////////////////////////////////////////////////////////////////////////////
--
----------------------------------------------------
function AIDebugToggle()
if(g_AIDebugToggleOn == 0) then
-- System.Log("___AIDebugToggle switching on");
g_AIDebugToggleOn=1;
System.SetCVar( "ai_DebugDraw",1 );
else
-- System.Log("___AIDebugToggle switching off");
System.SetCVar( "ai_DebugDraw",0 );
g_AIDebugToggleOn=0;
end
end
----------------------------------------------------
-- Removes a value from a table
function RemoveFromTable(tbl, ent)
for i,v in ipairs(tbl) do
if (v == ent) then
table.remove(tbl, i);
break;
end
end
end
-- Inserts a value into a table unless it is already present
function InsertIntoTable(tbl, ent)
local inside = false;
for i,v in ipairs(tbl) do
if (v == ent) then
inside = true;
break;
end
end
if (not inside) then
table.insert(tbl, ent);
end
end
-- Checks if a value is already inside a table
function IsInsideTable(tbl, ent)
for i,v in ipairs(tbl) do
if (v == ent) then
return true;
end
end
return false;
end
function SafeKillTimer(timer)
if (timer) then
Script.KillTimer(timer)
end
end
@@ -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",
},
}
+31
View File
@@ -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",
},
}
+277
View File
@@ -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 = {
}
+214
View File
@@ -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,
},
}
@@ -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.
--
--
----------------------------------------------------------------------------------------------------
-- require with:
-- local gameplayMultiHandler = require('scripts.utils.components.gameplayutils')
-- use like:
-- self.gameplayHandlers = gameplayMultiHandler.ConnectMultiHandlers{
-- [GameplayNotificationId("jump")] = {
-- OnEventBegin = function(floatValue) self:JumpStart(floatValue) end,
-- OnEventUpdating = function(floatValue) self:Jumping(floatValue) end,
-- OnEventEnd = function(floatValue) self:JumpEnded(floatValue) end,
-- },
-- }
-- disconnect from like this:
-- self.gameplayHandlers:Disconnect()
local multiHandlers = require('scripts.utils.components.MultiHandlers')
return {
ConnectMultiHandlers = multiHandlers(GameplayNotificationBus, GameplayNotificationId),
}
@@ -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.
--
--
----------------------------------------------------------------------------------------------------
-- require with:
-- local inputMultiHandler = require('scripts.utils.components.inpututils')
-- self.inputHandlers = inputMultiHandler.ConnectMultiHandlers{
-- [InputEventNotificationId("jump")] = {
-- OnPressed = function(floatValue) self:JumpPressed(floatValue) end,
-- OnHeld = function(floatValue) self:JumpHeld(floatValue) end,
-- OnReleased = function(floatValue) self:JumpReleased(floatValue) end,
-- },
-- }
-- disconnect from like this:
-- self.inputHandlers:Disconnect()
local inputMultiHandlers = require('scripts.utils.components.MultiHandlers')
return {
ConnectMultiHandlers = inputMultiHandlers(InputEventNotificationBus, InputEventNotificationId),
}
@@ -0,0 +1,74 @@
----------------------------------------------------------------------------------------------------
--
-- 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.
--
--
----------------------------------------------------------------------------------------------------
--This utility function allows you to easily create handlers when needing to handle multiple IDs.
--Common examples are inputs (where you have multiple key presses/actions you need to handle) and
--gameplay notifications (where there's several gameplay events your component needs to handle).
--See GameplayUtils.lua and InputUtils.lua as examples.
-- require with:
-- local multiHandlers = require('scripts.utils.components.multihandlers')
-- create multihandlers like:
-- return {
-- ConnectMultiHandlers = multiHandlers(GameplayNotificationBus, GameplayEventNotificationId),
-- }
local function ConnectMultiHandlers(bus, idType)
-- Generate listener constructor
return function(eventTable)
-- Our object emulating an ebus handler
local proxyHandler = {
handlers = { }
}
-- Connect to the bus for each id/handler passed
for busId, handlers in pairs(eventTable) do
Debug.Error(typeid(busId) == typeid(idType), "Wrong event id type, expected " .. tostring(typeid(busId)) .. " but got " .. tostring(typeid(idType)))
-- Setup proxy table
proxyHandler.handlers[busId] = {
originalHandlerTable = handlers; -- Reference to original handler table passed
handlerTable = { } -- Table containing actual handler functions
}
local currentProxy = proxyHandler.handlers[busId]
-- For each event handler, wrap and copy to proxy handlerTable
for eventName, eventHandler in pairs(handlers) do
if (type(eventHandler) == 'function') then
-- drop the original handler table for the callback
currentProxy.handlerTable[eventName] = function(origHandlerTable, ...)
eventHandler(...)
end
else
Debug.Warning(false, string.format("Invalid value passed to multihandler for key %s: %s. Function expected.", eventName, type(eventHandler)))
end
end
-- add a handler keyed on busid. Store the handler and callback by strong reference
currentProxy.busHandler = bus.Connect(currentProxy.handlerTable, busId)
end
-- Setup disconnect
function proxyHandler:Disconnect()
for busId, handlers in pairs(self.handlers) do
handlers.busHandler:Disconnect()
handlers.handlerTable = nil
handlers.origHandlerTable = nil
end
self.handlers = nil
end
return proxyHandler
end
end
return ConnectMultiHandlers
+334
View File
@@ -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.
--
-- Original file Copyright Crytek GMBH or its affiliates, used under license.
--
--
-- Description: Containers for Lua
-- Docs:
--
----------------------------------------------------------------------------------------------------
local countTable = Set and Set.countTable or {};
-- Create factory and management table
Set = {};
Set.countTable = countTable;
-- All tables are registered in Set.countTable, therefore won't GCed!
-- Unless we make their entries weak references. See Lua docs.
-- The effect is that these references are ignored by the garbage collector.
setmetatable(Set.countTable, { __mode="kv" });
-- Create and return a new Set table
Set.New = function()
local nt = {}
Set.countTable[nt] = 0
return nt
end
Set.SerializeValues = function(tbl)
local result = {}
for k,v in pairs(tbl) do
local item = {}
table.insert( item, 1, k );
table.insert( item, 2, v );
table.insert( result, item );
end
return result
end
Set.DeserializeValues = function(tbl)
local result = Set.New()
for i,item in ipairs(tbl) do
Set.Add( result, item[1], item[2] );
end
return result;
end
Set.DeserializeEntities = function(tbl)
local result = Set.New()
for i,entityID in ipairs(tbl) do
Set.Add(result, entityID)
end
return result
end
Set.SerializeEntities = function(tbl)
local result = {};
for entityID,v in pairs(tbl) do
table.insert(result, entityID)
end
return result;
end
Set.DeserializeItems = function(tbl)
local result = Set.New();
for i,item in ipairs(tbl) do
if (item) then
Set.Add(result, item);
end
end
return result;
end
Set.SerializeItems = function(tbl)
local result = {};
local index = 1;
for item,v in pairs(tbl) do
result[index] = item;
index = index + 1;
end
return result;
end
-- Is this table registered as a Set?
-- When performance and best-effort execution are required, this function
-- can easily be reduced to a stub or even all calls to it removed with regexp
Set.Check = function(table)
-- Run-time checking
if (not Set.countTable[table]) then
-- Throwing an error here would be preferable
if (print) then
print(tostring(table).."is not registered as a Set");
else
System.Log(tostring(table).."is not registered as a Set");
end
System.ShowDebugger()
Set.throwAnError.throwAnError = true;
end
end
-- Add an entry into a Set iff it does not already exist
-- if v == nil, we set it to true - leaving it nil would break things
-- Returns true on success, false if entry already exists
Set.Add = function(table, k, v)
v = v or true;
Set.Check(table);
if (not table[k]) then
table[k] = v;
Set.countTable[table] = Set.countTable[table] + 1;
return true;
end
return false;
end
-- Removes an entry from a Set
-- if k == nil, does nothing, which is debatable semantics
-- Returns true on success, false if entry did not exist
Set.Remove = function(table, k)
Set.Check(table);
if (table[k]) then
table[k] = nil;
Set.countTable[table] = Set.countTable[table] - 1;
return true;
end
return false;
end
-- Get a value from a Set
-- Return the value or nil if none
Set.Get = function(table, k)
Set.Check(table);
return table[k]
end
-- Set the value associated with a key, even if it already exists
-- if v == nil, we set it to true - leaving it nil would break things
-- Returns true if it did already exist, false if not
Set.Set = function(table, k, v)
v = v or true;
Set.Check(table);
if (not table[k]) then
table[k] = v;
Set.countTable[table] = Set.countTable[table] + 1;
return false;
else
-- Replace, no need to change count
table[k] = v;
return true;
end
end
-- Get the number of entries in the Set
Set.Size = function(table)
Set.Check(table);
return Set.countTable[table];
end
-- Remove all entries
-- No return value
Set.RemoveAll = function(table)
Set.Check(table);
for k,v in pairs(table) do
table[k] = nil;
end
Set.countTable[table] = 0;
end
-- Add entries of one Set into another
-- Keys shared by both will not be overwritten
-- Returns true iff keys were disjoint, none shared
Set.Merge = function(dest, source)
local disjoint = true;
Set.Check(dest);
Set.Check(source);
for k,v in pairs(source) do
if (not Set.Add(dest, k, v)) then
disjoint = false;
end
end
return disjoint;
end
-- Iterating:
-- For now, treat a Set as any table.
-- This should change.
-- Utility/debugging function:
-- Sanity check a suspicious Set
-- Tries to find evidence of tampering
-- Returns true iff it passes
Set.SanityCheck = function(table)
-- Check this was created as a Set
Set.Check(table);
-- Find as many things as you can in the Set
local count = 0;
for i,v in pairs(table) do
count = count + 1;
end
local size = Set.Size(table);
if (count ~= size) then
System.Log("[Set] Sanity check failed - Set size is "..tostring(size)..", counted "..count);
return false;
end
-- Check that all entries have the same type
-- This is just good practice, rather than an error
local indexType = nil;
local valueType = nil;
for i,v in pairs(table) do
-- Check index
if (indexType) then
if (indexType ~= type(i)) then
System.Log("[Set] Sanity check failed - Found indices of both types "..indexType.." and "..type(i));
return false;
end
else
indexType = type(i);
end
-- Check value
if (valueType) then
if (valueType ~= type(v)) then
System.Log("[Set] Sanity check failed - Found values of both types "..valueType.." and "..type(v));
return false;
end
else
valueType = type(v);
end
end
return true;
end
-- Unit test
-- Return true for success or false on failure
Set.Test = function(fullTest)
local A = Set.New();
local B = Set.New();
if ( Set.Add(A, "key1", 1) == false ) then return false; end
if ( Set.Add(A, "key2") == false ) then return false; end
if ( Set.Add(A, "key3", 3) == false ) then return false; end
if ( Set.Add(A, "key1", 1) == true ) then return false; end
if ( Set.Remove(A, "key1") == false ) then return false; end
if ( Set.Get(A, "key2")== false ) then return false; end
if ( Set.Get(A, "key1") ~= nil ) then return false; end
if ( Set.Get(A, "key3") ~= 3 ) then return false; end
if ( Set.Size(A) ~= 2 ) then return false; end
Set.RemoveAll(A);
if ( Set.Size(A) ~= 0 ) then return false; end
if ( Set.Add(A, "key1", 1) == false ) then return false; end
if ( Set.Set(A, "key1", 9) == false ) then return false; end
if ( Set.Set(A, "key0", 9) == true ) then return false; end
if ( Set.Add(A, "keyF", 3) == false ) then return false; end
if ( Set.Size(A) ~= 3 ) then return false; end
if ( Set.Add(B, "key3", 3) == false ) then return false; end
if ( Set.Add(B, "key4", 4) == false ) then return false; end
if ( Set.Add(B, "key5", 5) == false ) then return false; end
if ( Set.Add(B, "key3", 3) == true ) then return false; end
if ( Set.Set(B, "key9") == true ) then return false; end
if ( Set.Get(B, "key9") == nil ) then return false; end
if (not Set.Merge(A,B)) then return false; end
if (Set.Size(A) ~= 7) then return false; end
if (Set.Merge(A,B)) then return false; end
if (Set.Size(A) ~= 7) then return false; end
if (fullTest) then
-- Check countTable and GC (slow)
-- Shouldn't assume there are no Sets when testing
collectgarbage();
local baseCount = 0;
for i,v in pairs(Set.countTable) do
baseCount = baseCount + 1;
end
B = nil;
collectgarbage();
local count = 0;
for i,v in pairs(Set.countTable) do
count = count + 1;
end
if (baseCount - count ~= 1) then return false; end
end
-- Move this line around for testing
do return true; end
return true;
end
-- Perform quick version of unit test
if (not Set.Test()) then
System.Log("Containers: ... Error - Failed Unit Test");
else
--System.Log("Containers: ... End loading!");
end
-- Useful testing lines in Editor:
-- #Script.ReloadScript("Scripts/Utils/Containers.lua");
-- #System.Log(tostring(Set.Test(true)))
+962
View File
@@ -0,0 +1,962 @@
----------------------------------------------------------------------------------------------------
--
-- 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.
--
--
----------------------------------------------------------------------------------------------------
EntityCommon =
{
TempPhysParams = { mass=0,density=0 },
TempPhysicsFlags = { flags_mask=0, flags=0 };
TempSimulationParams = { max_time_step=0.02 };
}
----------------------------------------------------------
-- Creates a new table that is derived class of parent entity.
----------------------------------------------------------
function MakeDerivedEntity( _DerivedClass,_Parent )
local derivedProperties = _DerivedClass.Properties;
_DerivedClass.Properties = {};
mergef(_DerivedClass,_Parent,1);
-- Add derived class properties.
mergef(_DerivedClass.Properties,derivedProperties,1);
_DerivedClass.__super = BasicEntity;
return _DerivedClass;
end
----------------------------------------------------------
-- Creates a new table that is derived class of parent entity.
-- The Child's Properties will override the ones from the parent
----------------------------------------------------------
function MakeDerivedEntityOverride( _DerivedClass,_Parent )
--local derivedProperties = _Parent.Properties;
--_Parent.Properties = {};
mergef(_DerivedClass,_Parent,1);
-- Add derived class properties.
--mergef(_DerivedClass.Properties,derivedProperties,1);
_DerivedClass.__super = _Parent;
return _DerivedClass;
end
----------------------------------
function BroadcastEvent( sender,Event )
-- Check if Event Target for this input event exists.
sender:ProcessBroadcastEvent( Event );
if (sender.Events) then
--System.Log( "Events found" );
local eventTargets = sender.Events[Event];
if (eventTargets) then
--System.Log( "Events Targets found" );
for i, target in pairs(eventTargets) do
local TargetId = target[1];
local TargetEvent = target[2];
--System.Log( "Target: "..TargetId.."/"..TargetEvent );
--System.Log( "Target: "..TargetEvent );
if (TargetId == 0) then
-- If TargetId refer to global Mission table.
if Mission then
local func = Mission["Event_"..TargetEvent];
if (func ~= nil) then
func( sender )
else
System.Log( "Mission does not support event "..TargetEvent );
end
end
else
-- If TargetId refer to Entity.
local entity = System.GetEntity(TargetId);
if (entity ~= nil) then
local TargetName=entity:GetName();
--System.Log( "Entity Named "..TargetName.." Found." );
--System.Log( "Calling method: "..TargetName..":Event_"..TargetEvent );
local func = entity["Event_"..TargetEvent];
if (func ~= nil) then
func( entity,sender )
-- else
-- System.Log( "Entity "..TargetName.." does not support event "..TargetEvent );
end
-- else
-- System.Log( "Entity Named "..TargetName.." Not Found." );
end
end
end
end
end
end
function DumpEntities()
local ents=System.GetEntities();
System.Log("Entities dump");
for idx,e in pairs(ents) do
local pos=e:GetPos();
local ang=e:GetAngles();
System.Log("["..tostring(e.id).."]..name="..e:GetName().." clsid="..e.class..format(" pos=%.03f,%.03f,%.03f",pos.x,pos.y,pos.z)..format(" ang=%.03f,%.03f,%.03f",ang.x,ang.y,ang.z));
end
end
function MakeTargetableByAI( entity )
if (not entity.Properties) then entity.Properties = {} end
if (not entity.Properties.esFaction) then
entity.Properties.esFaction = "";
end
function entity:RegisterWithAI()
if (self.Properties.esFaction ~= "") then
CryAction.RegisterWithAI(self.id, AIOBJECT_TARGET);
AI.ChangeParameter(self.id, AIPARAM_FACTION, self.Properties.esFaction);
end
end
local _onReset = entity.OnReset;
function entity:OnReset(...)
if (_onReset) then
_onReset(self, ...);
end
self:RegisterWithAI();
end
local _onSpawn = entity.OnSpawn;
function entity:OnSpawn(...)
if (_onSpawn) then
_onSpawn(self, ...);
end
self:RegisterWithAI();
end
end
function MakeAICoverEntity(entity)
if (not entity.Properties) then entity.Properties = {} end
if (not entity.Properties.bProvideAICover) then entity.Properties.bProvideAICover = 1 end
local tbl = entity.Server and entity.Server or entity
local _onStartGame = tbl.OnStartGame
tbl.OnStartGame = function(self)
if (self.PropertiesInstance.bProvideAICover ~= 0) and (AI ~= nil) then
AI.AddCoverEntity(self.id)
end
if (_onStartGame) then
_onStartGame(self)
end
end
end
function MakeKillable( entity )
if (not entity.Properties) then entity.Properties = {} end
if (not entity.Properties.Health) then entity.Properties.Health = {} end
local Health = entity.Properties.Health;
Health.MaxHealth = 500;
Health.bInvulnerable = 0;
Health.bOnlyEnemyFire = 1;
function entity:IsDead()
return self.dead;
end
function entity:SetupHealthProperties()
self.dead = nil;
self.health = self.Properties.Health.MaxHealth;
self.invulnerable = self.Properties.Health.bInvulnerable ~= 0;
self.friendlyFire = self.Properties.Health.bOnlyEnemyFire == 0;
end
if (not entity.Server) then entity.Server = {} end
if (not entity.Client) then entity.Client = {} end
function entity:GetHealthRatio()
local healthR = 1;
local maxHealth = self.Properties.Health.MaxHealth;
if (maxHealth > 0) then
healthR = self.health / maxHealth;
end
return healthR;
end
function entity:IsInvulnerable()
return self.invulnerable
end
function entity:GetMaxHealth()
return self.Properties.Health.MaxHealth;
end
local _onHit = entity.Server.OnHit;
function entity.Server:OnHit(hit)
if ((not self.health) or (self.IsInvulnerable == nil)) then
Log("$4%s:%s Health not initialized!", self.class, self:GetName());
self:SetupHealthProperties();
end
local result = false;
if (_onHit) then
result = _onHit(self, hit);
end
if (not result) then
if (self:IsInvulnerable()) then
self:ActivateOutput("Health", self:GetHealthRatio() * 100);
self:Event_Hit();
return false;
end
if (not self.friendlyFire) then
if (System.GetEntity(hit.shooterId) ~= nil) then
local reaction = AI.GetReactionOf(self.id, hit.shooterId);
if (reaction == Friendly) then
self:ActivateOutput("Health", self:GetHealthRatio() * 100);
self:Event_Hit();
return false;
end
end
end
self.health = self.health - hit.damage;
end
self:ActivateOutput("Health", self:GetHealthRatio() * 100);
self:Event_Hit();
if (self.health <= 0) then
self.dead = true;
self:Event_Dead();
return true;
end
end
local _onReset = entity.OnReset;
function entity:OnReset(...)
if (_onReset) then
_onReset(self, ...);
end
self:SetupHealthProperties();
end
local _onSpawn = entity.OnSpawn;
function entity:OnSpawn(...)
if (_onSpawn) then
_onSpawn(self, ...);
end
self:SetupHealthProperties();
end
function entity:Event_ResetHealth()
self.dead = nil;
self.health = self.Properties.Health.MaxHealth;
end
function entity:SetInvulnerability(invulnerable)
self.invulnerable = invulnerable;
if(not self.overrode_saveload) then
local _onSave = self.OnSave;
function self:OnSave(table)
if(_onSave) then
_onSave(self, table);
end
if(self.invulnerable) then
table.invulnerable = self.invulnerable;
end
if(self.dead) then
table.dead = self.dead;
end
if(self.health) then
table.health = self.health;
end
end
local _onLoad = self.OnLoad;
function self:OnLoad(table)
if(_onLoad) then
_onLoad(self, table);
end
if(table.invulnerable) then
self.invulnerable = table.invulnerable;
else
self.invulnerable = false;
end
if(table.dead) then
self.dead = table.dead;
else
self.dead = false;
end
if(table.health) then
self.health = table.health;
else
self.health = self.Properties.Health.MaxHealth;
end
end
self.overrode_saveload = true;
end
end
function entity:Event_MakeVulnerable()
self:SetInvulnerability(false);
end
function entity:Event_MakeInvulnerable()
self:SetInvulnerability(true);
end
function entity:Event_Dead()
self:TriggerEvent(AIEVENT_DISABLE);
BroadcastEvent(self, "Dead");
end
function entity:Event_Hit()
BroadcastEvent(self, "Hit");
end
if not entity.FlowEvents then entity.FlowEvents = {} end
local fe = entity.FlowEvents
fe.Inputs = fe.Inputs or {}
fe.Outputs = fe.Outputs or {}
fe.Inputs["ResetHealth"] = { entity.Event_ResetHealth, "any" };
fe.Inputs["MakeVulnerable"] = { entity.Event_MakeVulnerable, "any" };
fe.Inputs["MakeInvulnerable"] = { entity.Event_MakeInvulnerable, "any" };
fe.Outputs["Dead"] = "bool";
fe.Outputs["Hit"] = "bool";
fe.Outputs["Health"] = "float";
end
function MakeRenderProxyOptions( entity )
if (not entity.Properties) then entity.Properties = {} end
if (not entity.Properties.RenderProxyOptions) then entity.Properties.RenderProxyOptions = {} end
entity.Properties.RenderProxyOptions.bAnimateOffScreenShadow = 0;
function entity:SetRenderProxyOptions()
self.bAnimateOffScreenShadow = self.Properties.RenderProxyOptions.bAnimateOffScreenShadow ~= 0;
if (self.bAnimateOffScreenShadow) then
self:CreateRenderProxy();
end
self:SetAnimateOffScreenShadow(self.bAnimateOffScreenShadow);
end
local _onReset = entity.OnReset;
function entity:OnReset(...)
if (_onReset) then
_onReset(self, ...);
end
self:SetRenderProxyOptions();
end
local _onSpawn = entity.OnSpawn;
function entity:OnSpawn(...)
if (_onSpawn) then
_onSpawn(self, ...);
end
self:SetRenderProxyOptions();
end
end
-- makes an OnUsed event for designers on an entity...
-- usage:
-- MyEntity = { ... whatever you usually put here ... }
-- MakeUsable(MyEntity)
-- function MyEntity:OnSpawn() ...
-- function MyEntity:OnReset()
-- self:ResetOnUsed()
-- ...
-- end
function MakeUsable( entity )
if not entity.Properties then entity.Properties = {} end
entity.Properties.UseMessage = "";
entity.Properties.bUsable = 0;
function entity:IsUsable()
if not self.__usable then
self.__origUsable = self.Properties.bUsable;
self.__origPickable = self.Properties.bPickable;
if (self.Properties.bUsable==1 or self.Properties.bPickable==1) then
self.__usable = 1;
else
self.__usable = 0;
end
end
return self.__usable;
end
function entity:ResetOnUsed()
self.__usable = nil;
end
function entity:GetUsableMessage()
return self.Properties.UseMessage;
end
function entity:OnUsed(user, idx)
BroadcastEvent(self, "Used");
if (self.Base_OnUsed) then
self:Base_OnUsed(user, idx);
end
end
function entity:Event_Used()
BroadcastEvent(self, "Used");
end
function entity:Event_EnableUsable()
self.__usable = 1;
BroadcastEvent(self, "EnableUsable");
end
function entity:Event_DisableUsable()
self.__usable = 0;
BroadcastEvent(self, "DisableUsable");
end
end
function MakePickable( entity )
if not entity.Properties then entity.Properties = {} end;
entity.Properties.bPickable = 0;
end
function AddHeavyObjectProperty(entity)
if (not entity.Properties) then
entity.Properties = {};
end;
entity.Properties.bHeavyObject = 0;
end;
function MakeThrownObjectTargetable( entity )
-- Add property
if not entity.Properties then
entity.Properties = {};
end
if not entity.Properties.AutoAimTarget then
entity.Properties.AutoAimTarget = {};
end
entity.Properties.AutoAimTarget.bMakeTargetableOnThrown = 0;
entity.Properties.AutoAimTarget.InnerRadiusVolumeFactor = 0.35;
entity.Properties.AutoAimTarget.OuterRadiusVolumeFactor = 0.6;
entity.Properties.AutoAimTarget.SnapRadiusVolumeFactor = 1.25;
entity.Properties.AutoAimTarget.AfterThrownTargetableTime = 3.0;
-- Add callback functions
function entity:OnThrown()
if ((self.Properties.AutoAimTarget.bMakeTargetableOnThrown ~= 0) and (self:CanBeMadeTargetable())) then
Game.RegisterWithAutoAimManager(self.id, self.Properties.AutoAimTarget.InnerRadiusVolumeFactor, self.Properties.AutoAimTarget.OuterRadiusVolumeFactor, self.Properties.AutoAimTarget.SnapRadiusVolumeFactor);
Script.SetTimer(self.Properties.AutoAimTarget.AfterThrownTargetableTime * 1000, function() self:AfterThrownTimer(); end)
self.isTargetable = 1;
end
end
function entity:AfterThrownTimer()
if (self.isTargetable) then
Game.UnregisterFromAutoAimManager(self.id);
self.isTargetable = nil;
end
end
local _CanBeMadeTargetable = entity.CanBeMadeTargetable;
function entity:CanBeMadeTargetable(...)
if (_CanBeMadeTargetable) then
return _CanBeMadeTargetable(self, ...);
end
return true;
end
-- Override shutdown/reset
local _OnShutDown = entity.OnShutDown;
function entity:OnShutDown(...)
if _OnShutDown then
_OnShutDown(self, ...);
end
if (self.isTargetable) then
Game.UnregisterFromAutoAimManager(self.id);
self.isTargetable = nil;
end
end
local _OnReset = entity.OnReset;
function entity:OnReset(...)
if _OnReset then
_OnReset(self, ...);
end
if (self.isTargetable) then
Game.UnregisterFromAutoAimManager(self.id);
self.isTargetable = nil;
end
end
end
function AddInteractLargeObjectProperty(entity)
if (not entity.Properties) then
entity.Properties = {};
end;
entity.Properties.bInteractLargeObject = 0;
end;
function MakeSpawnable( entity )
entity.spawnedEntity = nil
-- setup some basic properties
if not entity.Properties then entity.Properties = {} end
local p = entity.Properties;
p.bSpawner = false;
p.SpawnedEntityName = "";
local _OnDestroy = entity.OnDestroy;
function entity:OnDestroy(...)
-- System.Log("OnDestroy"..tostring(self.id));
if self.whoSpawnedMe then
-- inform that I'm dead
self.whoSpawnedMe:NotifyRemoval(self.id);
end
if _OnDestroy then
_OnDestroy(self, ...);
end
end
function entity:NotifyRemoval(spawnedEntityId)
-- System.Log("NotifyRemoval"..tostring(self.id).." spawned="..tostring(spawnedEntityId));
-- clear spawnedEntity on original
if (self.spawnedEntity and self.spawnedEntity == spawnedEntityId) then
--System.Log("...Cleared");
self.spawnedEntity = nil;
self.lastSpawnedEntity = nil;
end
end
-- override some functions to have our code called also
local _OnReset = entity.OnReset;
function entity:OnReset(...)
--System.Log("reset");
self.lastSpawnedEntity = nil;
if self.spawnedEntity then
System.RemoveEntity(self.spawnedEntity);
self.spawnedEntity = nil;
end
if self.whoSpawnedMe then
System.RemoveEntity( self.id );
return
end
_OnReset(self, ...);
end
local _OnEditorSetGameMode = entity.OnEditorSetGameMode;
function entity:OnEditorSetGameMode(...)
self.lastSpawnedEntity = nil;
if self.spawnedEntity then
self.spawnedEntity = nil;
end
if (_OnEditorSetGameMode) then
_OnEditorSetGameMode(self, ...);
end
end
-- allow flowgraph forwarding
function entity:GetFlowgraphForwardingEntity()
if (self.spawnedEntity) then
return self.spawnedEntity;
else
return self.lastSpawnedEntity;
end
end
-- OnSpawned event
function entity:Event_Spawned()
BroadcastEvent(self, "Spawned")
end
if not entity.FlowEvents then entity.FlowEvents = {} end
local fe = entity.FlowEvents
-- normalize events
fe.Inputs = fe.Inputs or {}
fe.Outputs = fe.Outputs or {}
-- collate events
local allEvents = {}
local name, data
for name, data in pairs(fe.Outputs) do
allEvents[name] = data
end
for name, data in pairs(fe.Inputs) do
allEvents[name] = data
end
-- event rebinding
for name, data in pairs(allEvents) do
local isInput = fe.Inputs[name]
local isOutput = fe.Outputs[name]
local isDeath = (name=="Dead")
local _event = data
if type(_event) == "table" then
_event = _event[1]
else
_event = nil
end
entity["Event_"..name] = function(self, sender, param)
-- auto broadcast received things for outputs
if isOutput and (sender and sender.id == self.spawnedEntity or sender==self) then
-- AI.LogEvent( ">>broadcasting output event "..name );
BroadcastEvent(self, name)
end
-- forward events where necessary
if isInput and (self.spawnedEntity and ((not sender) or (self.spawnedEntity ~= sender.id))) then
local ent = System.GetEntity(self.spawnedEntity)
if _event and ent and ent ~= sender then
_event(ent, sender, param)
end
elseif _event and not self.spawnedEntity then
-- and pass through where not
_event(self, sender, param)
end
-- handle death events
if isDeath and (sender and sender.id == self.spawnedEntity) then
self.spawnedEntity = nil
end
end
end
-- spawn event
function entity:Event_Spawn()
local entityIdDone = self:Event_Spawn_Internal();
-- the entity needs the output being activated, is not enough to just activate the output on the entity that spawnedMe,
-- because the flowgraph could be already forwarded to the newly spawned entity (if the entity does not have the flowgraph associated, the output event will be just ignored)
if (entityIdDone ~= self.id) then
self:ActivateOutput("Spawned", self.id);
end
end
function entity:Event_Spawn_Internal()
if self.whoSpawnedMe then
-- we were spawned (and not placed on a level)...
-- GetForwardingEntity will make sure that this event
-- is sent here first, but this event *MUST* be handled
-- by our spawner
return self.whoSpawnedMe:Event_Spawn_Internal()
else
if self.spawnedEntity then
return nil
end
local params = {
class = self.class;
position = self:GetPos(),
orientation = self:GetDirectionVector(1),
scale = self:GetScale(),
archetype = self:GetArchetype(),
properties = self.Properties,
propertiesInstance = self.PropertiesInstance,
}
if (self.InitialPosition) then
params.position = self.InitialPosition;
end
if self.Properties.SpawnedEntityName ~= "" then
params.name = self.Properties.SpawnedEntityName
else
params.name = self:GetName().."_s"
end
local ent = System.SpawnEntity(params, self.id)
if ent then
self.spawnedEntity = ent.id
self.lastSpawnedEntity = ent.id;
if not ent.Events then ent.Events = {} end
local evts = ent.Events
for name, data in pairs(self.FlowEvents.Outputs) do
if not evts[name] then evts[name] = {} end
table.insert(evts[name], {self.id, name})
end
ent.whoSpawnedMe = self;
ent:SetupTerritoryAndWave();
--self:Event_Spawned();
self:ActivateOutput("Spawned", ent.id);
return self.id;
end
end
end
-- spawn event keep
function entity:Event_SpawnKeep()
local params =
{
class = self.class;
position = self:GetPos(),
orientation = self:GetDirectionVector(1),
scale = self:GetScale(),
archetype = self:GetArchetype(),
properties = self.Properties,
propertiesInstance = self.PropertiesInstance,
}
local rndOffset = 1;
params.position.x = params.position.x + random(0,rndOffset*2)-rndOffset;
params.position.y = params.position.y + random(0,rndOffset*2)-rndOffset;
params.name = self:GetName()
local ent = System.SpawnEntity(params, self.id)
if ent then
self.spawnedEntity = ent.id
self.lastSpawnedEntity = ent.id;
if not ent.Events then ent.Events = {} end
local evts = ent.Events
for name, data in pairs(self.FlowEvents.Outputs) do
if not evts[name] then evts[name] = {} end
table.insert(evts[name], {self.id, name})
end
-- ent.whoSpawnedMe = self;
--self:Event_Spawned();
self:ActivateOutput("Spawned", ent.id);
end
end
-- hidhing/unhiding should be done inside disable/enable
-- function entity:Event_Hide()
-- self:Hide(1)
-- end
fe.Inputs["Spawn"] = {entity.Event_Spawn, "bool"}
-- fe.Inputs["Hide"] = {entity.Event_Hide, "bool"}
fe.Outputs["Spawned"] = "entity";
end
-----------------------------------------------------------------------------------------
-- Setup the collision filtering for the entity
-----------------------------------------------------------------------------------------
function SetupCollisionFiltering( entity )
-- Have we got an entity and a physics collision filtering table
if (entity == nil) then return end
if (entity.Properties == nil) then entity.Properties = {} end
if (entity.Properties.Physics == nil) then entity.Properties.Physics = {} end
-- Populate the table with the basic collision classes
-- These are enumurated in the global g_PhysicsCollisionClass
-- which is created by the game code
entity.Properties.Physics.CollisionFiltering = {};
local c = entity.Properties.Physics.CollisionFiltering;
c.collisionType = {}
c.collisionIgnore = {}
if (g_PhysicsCollisionClass == nil) then return end
for i, v in pairs(g_PhysicsCollisionClass) do
c.collisionType[i] = 0;
c.collisionIgnore[i] = 0;
end
end
function GetCollisionFiltering( entity )
local output = {}
output.collisionClass = 0;
output.collisionClassIgnore = 0;
if (entity.Properties.Physics==nil) then return output; end
if (entity.Properties.Physics.CollisionFiltering==nil) then return output; end
local c = entity.Properties.Physics.CollisionFiltering;
for i,v in pairs(c.collisionType) do
local gameSideFlag = g_PhysicsCollisionClass[i];
if (gameSideFlag ~= nil and v==1) then
output.collisionClass = output.collisionClass + gameSideFlag;
end
end
for i,v in pairs(c.collisionIgnore) do
local gameSideFlag = g_PhysicsCollisionClass[i];
if (gameSideFlag ~= nil and v==1) then
output.collisionClassIgnore = output.collisionClassIgnore + gameSideFlag;
end
end
return output;
end
function ApplyCollisionFiltering(entity, filtering)
if (filtering.collisionClass ~= 0 or filtering.collisionClassIgnore ~= 0) then
entity:SetPhysicParams(PHYSICPARAM_COLLISION_CLASS, filtering );
end
end
---------------------------------------------------------------------------------------------------
-- Physicalize rigid body.
---------------------------------------------------------------------------------------------------
--GlobalPhysicsSimParams = { max_logged_collisions = 1 };
EntityCommon.PhysicalizeRigid = function( entity,nSlot,Properties,bActive )
local Mass = Properties.Mass;
local Density = Properties.Density;
if bActive and bActive==0 then
Mass = 0.0; Density = 0.0;
end
local physType;
if (Properties.bArticulated == 1) then
physType = PE_ARTICULATED;
else
if (Properties.bRigidBody == 1) then
physType = PE_RIGID;
else
physType = PE_STATIC;
end
end
local TempPhysParams = EntityCommon.TempPhysParams;
TempPhysParams.density = Density;
TempPhysParams.mass = Mass;
TempPhysParams.flags = 0;
if (Properties.CGFPropsOverride) then
TempPhysParams.CGFprops = "";
for key,value in pairs(Properties.CGFPropsOverride) do
if (type(value)=="table") then
for key1,value1 in pairs(value) do
if (value1~="") then
TempPhysParams.CGFprops = TempPhysParams.CGFprops..key1.."="..value1.."\n";
end
end
else
if (value~="") then
TempPhysParams.CGFprops = TempPhysParams.CGFprops..key.."="..value.."\n";
end
end
end
end
entity:Physicalize( nSlot, physType, TempPhysParams );
--entity:SetPhysicParams(PHYSICPARAM_SIMULATION, GlobalPhysicsSimParams );
if (Mass>0 or Density>0) then
ApplyCollisionFiltering(entity, { collisionClass=gcc_rigid; } );
end
if(Properties.bInteractLargeObject==1) then
ApplyCollisionFiltering(entity, { collisionClass=gcc_large_kickable; } );
end
ApplyCollisionFiltering(entity, GetCollisionFiltering(entity));
if (Properties.Simulation) then
local SimulationSrc = Properties.Simulation;
local SimulationDst = EntityCommon.TempSimulationParams;
for key,value in next,SimulationDst,nil do SimulationDst[key] = nil; end
for key,value in next,SimulationSrc,nil do
if (key~="max_time_step" or value<0.0199 or value>0.0201) and (key~="sleep_speed" or value<0.0399 or value>0.0401) then SimulationDst[key] = value; end
end
entity:SetPhysicParams(PHYSICPARAM_SIMULATION, SimulationDst);
end
local Buoyancy = Properties.Buoyancy;
if (Buoyancy) then
entity:SetPhysicParams(PHYSICPARAM_BUOYANCY, Buoyancy);
end
local ForeignData = Properties.ForeignData;
if(ForeignData and ForeignData.bMovingPlatform == 1) then
entity:SetPhysicParams(PHYSICPARAM_FOREIGNDATA, { foreignFlags=FOREIGNFLAGS_MOVING_PLATFORM } );
end
-----------------------------------------------------------------------------
-- Set physical flags.
-----------------------------------------------------------------------------
local PhysFlags = EntityCommon.TempPhysicsFlags;
PhysFlags.flags = 0;
if (Properties.bPushableByPlayers == 1) then
PhysFlags.flags = pef_pushable_by_players;
end
if (Simulation and Simulation.bFixedDamping and Simulation.bFixedDamping==1) then
PhysFlags.flags = PhysFlags.flags+pef_fixed_damping;
end
if (Simulation and Simulation.bUseSimpleSolver and Simulation.bUseSimpleSolver==1) then
PhysFlags.flags = PhysFlags.flags+ref_use_simple_solver;
end
if (Properties.bCanBreakOthers==nil or Properties.bCanBreakOthers==0) then
PhysFlags.flags = PhysFlags.flags+pef_never_break;
end
if (Properties.MP and Properties.MP.bClientOnly) then
-- allow breaking on the client
PhysFlags.flags = PhysFlags.flags+pef_override_impulse_scale;
end
PhysFlags.flags_mask = pef_fixed_damping + ref_use_simple_solver + pef_pushable_by_players + pef_never_break + pef_override_impulse_scale;
entity:SetPhysicParams( PHYSICPARAM_FLAGS,PhysFlags );
-----------------------------------------------------------------------------
if (Properties.bResting == 0) then
entity:AwakePhysics(1);
else
entity:AwakePhysics(0);
end
end
-------------------------------------------------------------------------------
-- Compare entities by name (for table.sort)
-------------------------------------------------------------------------------
function CompareEntitiesByName( ent1, ent2 )
return ent1:GetName() < ent2:GetName()
end
function MakeCompareEntitiesByDistanceFromPoint( point )
function CompareEntitiesByDistanceFromPoint( ent1, ent2 )
distance1 = DistanceSqVectors( ent1:GetWorldPos(), point )
distance2 = DistanceSqVectors( ent2:GetWorldPos(), point )
return distance1 > distance2
end
return CompareEntitiesByDistanceFromPoint
end
-------------------------------------------------------------------------------
-- Called by Pool System when an Entity is bookmarked for pool usage
-- - Gives us its EntityId and PropertiesInstance tables for logic-driven utilities
-------------------------------------------------------------------------------
function OnEntityBookmarkCreated( entityId, propertiesInstance )
local waveName = nil;
if (propertiesInstance and propertiesInstance.AITerritoryAndWave) then
waveName = propertiesInstance.AITerritoryAndWave.aiwave_Wave;
end
if (waveName and waveName ~= "<None>") then
-- Notify territory and wave
AddBookmarkedToWave(entityId, waveName);
return false;
end
return true;
end
+420
View File
@@ -0,0 +1,420 @@
----------------------------------------------------------------------------------------------------
--
-- 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.
--
--
----------------------------------------------------------------------------------------------------
function ConstVec(v)
return v
end
----------------------------------------------------
-- global Vectors table and some vector functions
----------------------------------------------------
g_Vectors =
{
v000=ConstVec({x=0,y=0,z=0}),
v001=ConstVec({x=0,y=0,z=1}),
v010=ConstVec({x=0,y=1,z=0}),
v011=ConstVec({x=0,y=1,z=1}),
v100=ConstVec({x=1,y=0,z=0}),
v101=ConstVec({x=1,y=0,z=1}),
v110=ConstVec({x=1,y=1,z=0}),
v111=ConstVec({x=1,y=1,z=1}),
up = ConstVec({x=0,y=0,z=1}),
down = ConstVec({x=0,y=0,z=-1}),
temp={x=0,y=0,z=0},
tempColor={x=0,y=0,z=0},
temp_v1={x=0,y=0,z=0},
temp_v2={x=0,y=0,z=0},
temp_v3={x=0,y=0,z=0},
temp_v4={x=0,y=0,z=0},
temp_v5={x=0,y=0,z=0},
temp_v6={x=0,y=0,z=0},
vecMathTemp1={x=0,y=0,z=0},
vecMathTemp2={x=0,y=0,z=0},
}
-----------------------------------------------------------------------------
-- Math constants
-----------------------------------------------------------------------------
g_Rad2Deg = 180/math.pi;
g_Deg2Rad = math.pi/180;
g_Pi = math.pi;
g_2Pi = 2*math.pi;
g_Pi2 = 0.5*math.pi;
-----------------------------------------------------------------------------
-- Import commonly used math functions from math. table to global namespace.
-----------------------------------------------------------------------------
random = math.random;
math.randomseed(os.time()); -- seed and pop
random();
-----------------------------------------------------------------------------
function IsNullVector(a)
return (a.x==0 and a.y==0 and a.z ==0);
end
function IsNotNullVector(a)
return (a.x~=0 or a.y~=0 or a.z ~=0);
end
function LengthSqVector(a)
return (a.x * a.x + a.y * a.y + a.z * a.z);
end
function LengthVector(a)
return math.sqrt(LengthSqVector(a));
end
function DistanceSqVectors(a, b)
local x = a.x-b.x;
local y = a.y-b.y;
local z = a.z-b.z;
return x*x + y*y + z*z;
end
function DistanceSqVectors2d(a, b)
local x = a.x-b.x;
local y = a.y-b.y;
return x*x + y*y;
end
function DistanceVectors(a, b)
local x = a.x-b.x;
local y = a.y-b.y;
local z = a.z-b.z;
return math.sqrt(x*x + y*y + z*z);
end
-----------------------------------------------------------------------------
function dotproduct3d(a,b)
return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
end
-----------------------------------------------------------------------------
function dotproduct2d(a,b)
return (a.x * b.x) + (a.y * b.y);
end
function LogVec(name,v)
Log("%s = (%f %f %f)",name,v.x,v.y,v.z);
end
function ZeroVector(dest)
dest.x=0;
dest.y=0;
dest.z=0;
end
function CopyVector(dest,src)
dest.x=src.x;
dest.y=src.y;
dest.z=src.z;
end
----------------------------------
function SumVectors(a,b)
return {x=a.x+b.x,y=a.y+b.y,z=a.z+b.z};
end
function NegVector(a)
a.x = -a.x;
a.y = -a.y;
a.z = -a.z;
end
----------------------------------
function SubVectors(dest,a,b)
dest.x = a.x - b.x;
dest.y = a.y - b.y;
dest.z = a.z - b.z;
end
----------------------------------
function FastSumVectors(dest,a,b)
dest.x=a.x+b.x;
dest.y=a.y+b.y;
dest.z=a.z+b.z;
end
----------------------------------
function DifferenceVectors(a,b)
return {x=a.x-b.x,y=a.y-b.y,z=a.z-b.z};
end
----------------------------------
function FastDifferenceVectors(dest,a,b)
dest.x=a.x-b.x;
dest.y=a.y-b.y;
dest.z=a.z-b.z;
end
----------------------------------
function ProductVectors(a,b)
return {x=a.x*b.x,y=a.y*b.y,z=a.z*b.z};
end
----------------------------------
function FastProductVectors(dest,a,b)
dest.x=a.x*b.x;
dest.y=a.y*b.y;
dest.z=a.z*b.z;
end
----------------------------------
function ScaleVector(a,b)
return {x=a.x*b,y=a.y*b,z=a.z*b};
end
function ScaleVectorInPlace(a,b)
a.x=a.x*b;
a.y=a.y*b;
a.z=a.z*b;
end
----------------------------------
function NormalizeVector(a)
local len=math.sqrt(LengthSqVector(a));
local multiplier;
if(len>0)then
multiplier=1/len;
else
multiplier=0.0001;
end
a.x=a.x*multiplier;
a.y=a.y*multiplier;
a.z=a.z*multiplier;
return a
end
----------------------------------
function FastScaleVector(dest,a,b)
dest.x=a.x*b;
dest.y=a.y*b;
dest.z=a.z*b;
end
--linear interpolation
----------------------------------
function LerpColors(a,b,k)
g_Vectors.tempColor.x = a.x+(b.x-a.x)*k
g_Vectors.tempColor.y = a.y+(b.y-a.y)*k
g_Vectors.tempColor.z = a.z+(b.z-a.z)*k
return g_Vectors.tempColor;
end
----------------------------------
function Lerp(a,b,k)
return (a + (b - a)*k);
end
----------------------------------
function __max(a, b)
if (a > b) then
return a;
else
return b;
end
end
----------------------------------
function __min(a, b)
if (a < b) then
return a;
else
return b;
end
end
----------------------------------
function clamp(_n, _min, _max)
if (_n > _max) then _n = _max; end
if (_n < _min) then _n = _min; end
return _n;
end
----------------------------------
function Interpolate(actual,goal,speed)
local delta = goal - actual;
if (math.abs(delta)<0.001) then
return goal;
end
local res = actual + delta * __min(speed,1.0);
return res;
end
-----------------------------------
function sgn(a)
if (a == 0) then
return 0;
elseif (a > 0) then
return 1;
else
return -1;
end
end
-----------------------------------
function sgnnz(a)
return (a>=0) and 1 or -1;
end
-----------------------------------
function sqr(a)
return a*a;
end
-----------------
function randomF(a,b)
if (a>b) then
local c = b;
b = a;
a = c;
end
local delta = b-a;
return (a + math.random()*delta);
end
function VecRotate90_Z(v)
local x = v.x;
v.x = v.y;
v.y = -x;
end
function VecRotateMinus90_Z(v)
local x = v.x;
v.x = -v.y;
v.y = x;
end
function iff(c,a,b)
if c then return a else return b end
end
-----------------------------------------------------------------------------
-- calculate cross product
function crossproduct3d( dest, p, q )
dest.x = p.y*q.z-p.z*q.y;
dest.y = p.z*q.x-p.x*q.z;
dest.z = p.x*q.y-p.y*q.x;
end
-- rotate vector p around vector r by angle
-- the length of r needs to be 1
function RotateVectorAroundR( dest, p, r, angle )
-- p' = v1 + v2 +v3
-- v1 = pcosA
-- v2 = r**psinA;
-- v3 = r< r,p >( 1- cosA );
local cosValue = math.cos( angle );
local sinValue = math.sin( angle );
local v1 = {};
local v2 = {};
local v3 = {};
local vTmp = {};
-- v1
CopyVector( v1, p );
FastScaleVector( v1, v1, cosValue );
-- v2
CopyVector( vTmp, p );
FastScaleVector( vTmp, vTmp, sinValue );
crossproduct3d( v2, r, vTmp );
-- v3
CopyVector( v3, r );
FastScaleVector( v3, v3, dotproduct3d( r, p ) );
FastScaleVector( v3, v3, 1.0 - cosValue );
-- p'
CopyVector( dest, v1 );
FastSumVectors( dest, v1, v2 );
FastSumVectors( dest, dest, v3 );
end
-- project P to the surface whose normal vector is N.
function ProjectVector( dest, P, N )
-- projected vector is vector X (output)
-- X =P+(-P*N)N
local minusP ={};
FastScaleVector( minusP , P , -1.0 );
local t = dotproduct3d( minusP, N );
CopyVector( dest , N );
FastScaleVector( dest , dest , t );
FastSumVectors( dest , dest , P );
end
-- get a distance between line(pt+q) and point(a)
function DistanceLineAndPoint( a, p, q )
-- d=|| p * (a-q) || / ||p||
local length = LengthVector( p );
local outerProduct;
local vOuterProduct = {};
local vTmp = {};
local d;
SubVectors( vTmp, a, q );
crossproduct3d( vOuterProduct, p, vTmp );
outerProduct =LengthVector( vOuterProduct );
if ( length>0.01 ) then
d = outerProduct/length;
else
d = 0.0;
end
return d;
end
-- Get normalized direction vector from point 'a' to point 'b'
function GetDirection(a, b)
local dir = {};
SubVectors(dir, b, a);
NormalizeVector(dir);
return dir;
end
function GetAngleBetweenVectors2D(a, b)
return math.acos(dotproduct2d(a, b));
end
function GetAngleBetweenVectors(a, b)
return math.acos(clamp(dotproduct3d(a, b), -1, 1));
end