// September 2015 // Levee Patroller / Dijk Patrouille // This source file is (c) by Deltares. This source file is open source but only available to select users. Do not redistribute without written permission of Stichting Deltares, Delft, The Netherlands. // This header has been automatically generated. //============================================================================= // Levee Failure // // This object represents a single failure to be attached to a leveetile (piping, macro, etc) // // ------------------------------------------------------------ // Created by Almar Joling // © 2007, Geodelft // // Date Id Modification // 2007-10-01 jln Header created //============================================================================= class LeveeFailure extends Actor placeable; #exec OBJ LOAD FILE=PrimDikeSM.usx #exec OBJ LOAD FILE=SecDikeSM.usx #exec OBJ LOAD FILE=TrafficSignsSM.usx #exec OBJ LOAD FILE=ArnesEnvironmentSM.usx #exec OBJ LOAD FILE=SmitteyMesh.usx const deg2rad = 0.0174532925; Const URotToRadian = 0.000095873799; Const DegreeToRadian = 0.01745329252; Const RadianToURot = 10430.3783505; Const RadianToDegree = 57.2957795131; //Const Pi = 3.1415926535897932384626433832795; /// Pointer to the created scripted trigger object, when creating this failure: var DScriptedTrigger FailureScript; /// To speed things up: var float speedfactor; //1.00; //1.00; //0.25; /// List of failure signal present in this failure var array Signals; /// List of measures that this failure accepts var array Measures; /// The actual failure mechanism filled in by the level designer var() GeoEnums.FailingMechanisms Mechanism; /// To which LeveeTile are we linked? var LeveeTile LinkedTile; /// List of actors that will only be visible if failure is active var GraphicalActors OnlyVisibleIfActive; /// List of actors that will only be visible if failure is inactive var GraphicalActors OnlyVisibleIfNotActive; /// Visible if Active count: var int VIACount; /// Used for a hack: var name nTempName; /// Unique ID in the level!!! var name id; /// Bounding box min and max position for this failure var vector vMin, vMax; /// Tile width and height: var float tilewidth, tileheight; var GeoEnums.eTileSize FailureSize; /// Location where the redmarker will be moved to when it is moved. var vector RedMarkerLocation; /// The exports puts objects in a 0 based rotation. For some calculations, we need to use the original rotation as used in the exported map /// This value is used for this. It defaults to 16384, but for some (likely in level 2) it will have to be changed to match the rotation /// of the original failure. The exporter should do this for you. /// This is YAW only!! var int RelativeRotation; /// Primary mesh scaler, the tutorial failure has a different mesh scale, and we have to take this into account. Default is ofcourse 1. var float MeshScale; var string NL_FailureName, EN_FailureName; var DynamicMeshActor dCorners[4]; var bool ShowboundingBoxes; /// Bounding box points. var vector BoundingBoxCache[4]; var vector BoundingBoxScale; event SetInitialState() { //Log("Set initial state LeveeFailure"); } function Actor GetActor(name Tag) { local Actor A; /// Find actor by tag: ForEach AllActors(class'Actor',A,Tag) { return A; } return none; } function SetFailureRelativeRotation(int value) { RelativeRotation = value; } function InitFailure() { if (LinkedTile == none) { Log("WARNING: LinkedTile is null, use SetTile first! (LeveeFailure.uc)"); } /// Defautl scale: BoundingBoxScale = vect(0,0,0); tilewidth = (self.OctreeBox.Max.x - self.OctreeBox.Min.x) / 2; tileheight = (self.OctreeBox.Max.y - self.OctreeBox.Min.y) / 2; /// Set RelativeRotation = 16384; VIACount = 0; if (OnlyVisibleIfActive == None) { OnlyVisibleIfActive = Spawn(class 'GraphicalActors'); } if (OnlyVisibleIfNotActive == None) { /// Spawn if necessary: OnlyVisibleIfNotActive = Spawn(class 'GraphicalActors'); } //Log("Only visible if active: " @ self.LinkedTile.name @ " " @ OnlyVisibleIfActive @ " " @ OnlyVisibleIfActive.GraphActor.Length); //Log("Only visible if not active: " @ self.LinkedTile.name @ " " @ OnlyVisibleIfNotActive @ " " @ OnlyVisibleIfNotActive.GraphActor.Length); SetFailureOptions(); CreateObjects(); CreateTriggers(); CreateSignals(); CreateMeasures(); CreateMeasureScripts(); NL_FailureName = "(not defined)"; EN_FailureName = "(not defined)"; ShowboundingBoxes = bool(Localize("DebugInfo", "Showboxes", "GeoSimulator")); } function SetFailureOptions() { linkedTile.NL_FailureName = NL_FailureName; linkedTile.NL_FailureName = EN_FailureName; } /// Store the tile object here, so that we can reference it to acquire various properties (rotation, location); function SetTile(LeveeTile t) { self.LinkedTile = t; } function LeveeTile GetTile() { return self.LinkedTile; } function CreateObjects() { /// Log("Creating failure objects"); local DynamicMeshActor sMA ; local int multiplier; local int i; multiplier = -1; /// New test: if (LinkedTile.TileSize == TS_48M && FailureSize == TS_32M) { /// But we are 32... /// Add additional piece of levee & road. Log ("This is a 32m object in 48m space, adding extra tile"); /// Yes, I don't like this either, but there isn't another easy fix. /// The riprap needs to be positioned on the opposite site of default. if (self.IsA('LeveeFailureErosionOuterRipRap_Straight')) multiplier = 1; if (self.ISA('LeveeFailureErosionOuterFloatingWaste')) { Log("This is an floating waste object, returning..."); return; } sMA = CreateMesh(RotateVector(0,4096*multiplier,0), id$"StaticMeshActor", StaticMesh'PrimDikeSM.Base.PrimDike16Straight'); Log("Linkedtile location: " @ LinkedTile.Location); Log("Erosion outer location: " @ sMA.Location); RotationOffset(sMA, LinkedTile.Rotation, 0,0,0); Log("Erosion outer location: " @ sMA.Location); sMA = CreateMesh(RotateVector(0,6144*multiplier,0), id$"StaticMeshActor", StaticMesh'PrimDikeSM.Base.PrimDyke16Road'); RotationOffset(sMA, LinkedTile.Rotation, 0,0,0); } /// Is this a 16m tile in a 32m tile? if (LinkedTile.LeveeType == LT_RegionalLeveeWithoutRoad && LinkedTile.TileSize == TS_32M && FailureSize == TS_16M) { /// But we are 32... /// Add additional piece of levee & road. //sMA = CreateMesh(RotateVector(-2048,0,0), id$"StaticMeshActor", StaticMesh'SecDikeSM.SecDike.boezem_recht_no_road'); //RotationOffset(sMA, LinkedTile.Rotation, 0,0,0); //sMA = CreateMesh(RotateVector(0,-6144, 300), id$"StaticMeshActor", StaticMesh'PrimDikeSM.Base.PrimDyke16Road'); //RotationOffset(sMA, LinkedTile.Rotation, 0,0,0); /// Make the hidden extra geometry visible again: for(i=0; i < OnlyVisibleIfNotActive.GraphActor.Length; i++) { if (OnlyVisibleIfNotActive.GraphActor[i].StaticMesh == StaticMesh'SecDikeSM.SecDike.boezem_recht_no_road') { Log("Making a tile visible again"); /// Make it visible again: OnlyVisibleIfNotActive.GraphActor[i].bLockLocation = true; /// We check on this later to not accidentally hide it again. OnlyVisibleIfNotActive.GraphActor[i].bHidden=false; } } } /// jln - 04-03-2009 Temp, create 4 corner markers to display the 4 corners of the failure boxes: ShowboundingBoxes = bool(Localize("DebugInfo", "Showboxes", "GeoSimulator")); if (ShowboundingBoxes) { dCorners[0] = Spawn(class'DynamicMeshActor'); dCorners[0].SetStaticMesh(StaticMesh'GeoGamePlay.Markers.RedMarker'); dCorners[1] = Spawn(class'DynamicMeshActor'); dCorners[1].SetStaticMesh(StaticMesh'GeoGamePlay.Markers.RedMarker'); dCorners[2] = Spawn(class'DynamicMeshActor'); dCorners[2].SetStaticMesh(StaticMesh'GeoGamePlay.Markers.RedMarker'); dCorners[3] = Spawn(class'DynamicMeshActor'); dCorners[3].SetStaticMesh(StaticMesh'GeoGamePlay.Markers.RedMarker'); } } function CreateTriggers() { /// Log("Creating failure triggers"); } function CreateSignals() { /// Log("Creating failure signals"); } function CreateMeasures() { /// Log("Creating failure measures"); } function CreateMeasureScripts() { /// Log("Creating measure scripts"); } function bool Encompasses(actor a, optional bool notolerance) { // local vector min,max; // local Rotator NR; // min = vMin; //max = vMax; return EncompassesVector(a.location, true); } function bool EncompassesNT(actor a) { local vector min,max; min = vMin ; max = vMax; Log("EncompassesNT()"); return EncompassesVector(a.location, true); } /// jln - 03-03-2009 NEw encompass function function bool EncompassesVector(vector location, optional bool notolerance) { local Vector corners[4]; local vector minBounds, maxBounds, center; /// Is the max y smaller than the min x? // local bool invertx, inverty; // local float tempval; local int rotation; local vector draws; minBounds = vMin - BoundingBoxScale; maxBounds = vMax + BoundingBoxScale; center = (minbounds + maxbounds) / 2; minbounds -= center; maxbounds -= center; /// Not the best code there is, but it works... switch (self.Linkedtile.Rotation.Yaw) { case 32768: rotation = self.Linkedtile.rotation.Yaw; // - 32768; break; case 49158: rotation = self.Linkedtile.rotation.Yaw - 16384; // + 16384; break; default: rotation = (self.Linkedtile.rotation.Yaw - 16384); // + 16384; break; } /// Rotate box: corners[0] = mvect( minBounds.x, minBounds.y, minBounds.z ); // xyz corners[1] = mvect( maxBounds.x, minBounds.y, minBounds.z ); // Xyz corners[2] = mvect( maxBounds.x, maxBounds.y, minBounds.z ); // XYz corners[3] = mvect( minBounds.x, maxBounds.y, minBounds.z ); // xYz corners[0] = RotateVectorVec(corners[0], rotation, 0); corners[1] = RotateVectorVec(corners[1], rotation, 0); corners[2] = RotateVectorVec(corners[2], rotation, 0); corners[3] = RotateVectorVec(corners[3], rotation, 0); corners[0] += center; corners[1] += center; corners[2] += center; corners[3] += center; /// Store / cache BoundingBoxCache[0] = corners[0]; BoundingBoxCache[1] = corners[1]; BoundingBoxCache[2] = corners[2]; BoundingBoxCache[3] = corners[3]; //Log(" "); //Log(" "); //Log("Encompass new " @ location); if (ShowboundingBoxes) { dCorners[0].SetLocation(corners[0]); dCorners[1].SetLocation(corners[1]); dCorners[2].SetLocation(corners[2]); dCorners[3].SetLocation(corners[3]); dCorners[0].SetCollision(false,false,false); dCorners[1].SetCollision(false,false,false); dCorners[2].SetCollision(false,false,false); dCorners[3].SetCollision(false,false,false); draws = vect(4,4,75); dCorners[0].SetDrawScale3D(draws); dCorners[1].SetDrawScale3D(draws); dCorners[2].SetDrawScale3D(draws); dCorners[3].SetDrawScale3D(draws); } //Log("Point inside rect: " @ PointInsideRect(corners, location) @ self); return PointInsideRect(corners, location); } function bool PointInsideRect(vector verts[4], vector location) { local int nvert; local int i,j; local bool c; local float testx, testy; nvert = 4; testx = location.x; testy = location.y; j = nvert - 1; for (i = 0; i < nvert; i++) { if ( ((verts[i].y>testy) != (verts[j].y>testy)) && (testx < (verts[j].x-verts[i].x) * (testy-verts[i].y) / (verts[j].y-verts[i].y) + verts[i].x) ) c = !c; j = i; } return c; } function vector RotateVectorVec(vector pos, float YawAngle, float RelativeRotation) { local vector Loc; local float Yaw; Loc = vect(0,0,0); //LinkedTile.Location; //Loction of the Orginal Vector Yaw = (YawAngle + RelativeRotation ) * URotToRadian ; /// Rotate vector based on object rotation and position Loc.X += pos.x * cos(Yaw) - pos.y * sin(Yaw); Loc.Y += pos.x * sin(Yaw) + pos.y * cos(Yaw); Loc.Z += pos.z; return Loc; } function Vector mvect(float x, float y, float z) { local vector v; v.x = x; v.y = y; v.z = z; return v; } function ActivateFailures(bool bActiveTemp) { self.LinkedTile.bActive = bActiveTemp; log("]]]]]]]=======> Levee Tile Failure is set on " @ self.LinkedTile.name @ " " @ self.LinkedTile.bActive); if(bActiveTemp) { //Hide our own staticmesh: self.LinkedTile.bHidden = true; self.LinkedTile.SetCollision(false,false,false); OnlyVisibleIfActive.bForceSameLocation = true; OnlyVisibleIfActive.SetVisible(); if (OnlyVisibleIfNotActive != None) { OnlyVisibleIfNotActive.SetInVisible(); } } else { self.LinkedTile.bHidden = false; self.LinkedTile.SetCollision(true,true,true); OnlyVisibleIfNotActive.bForceSameLocation = true; if (OnlyVisibleIfNotActive != None) { OnlyVisibleIfNotActive.SetVisible(); } if (OnlyVisibleIfActive != None) OnlyVisibleIfActive.SetInVisible(); } } function EnableSpecialTimings() { local int i; local ACTION_WaitForTimer waitevent; Log("[EnableSpecialTimings] This is a training failure, and we are going to adjust timings now."); /// Loop through all script events and change timing if above a certain threshold. for(i = 0; i < FailureScript.Actions.Length; i++) { /// Correct event? if (ACTION_WaitForTimer(FailureScript.Actions[i]) != None) { /// Cast waitevent = ACTION_WaitForTimer(FailureScript.Actions[i]); /// Check timings. if (waitevent.PauseTime > 60) { /// adjust: //waitevent.PauseTime = 60 + (waitevent.PauseTime / 5); waitevent.PauseTime = 60 - 60*((600-waitevent.PauseTime )/ 600); Log("Adjust pausetime to: " @ waitevent.PauseTime); } } } } function CreateBoundingBox() { local int i; local vector v; Local DynamicMeshActor sMa; local rotator rot; local bool skipmesh; local float offsetx, offsety; local vector offset; vMin = vect(999999,999999,999999); vMax = vect(-999999,-999999,-999999); /// Loop through all actors of this tile: //Log(self @ "is active: " @ self.LinkedTile.bActive); if (self.LinkedTile.bActive == true) { for( i=0; i < OnlyVisibleIfActive.GraphActor.Length; i++ ) { /// We skip some meshes which cause problems because of their width: skipmesh = (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'SecDikeSM.MacroStab.SecMacroStabBase') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'SecDikeSM.Measures.Measure_Berm_Macro_Sec') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'PrimDikeSM.BreakTroughFX.WildWaterMeshPiping') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'SecDikeSM.Measures.Measure_Talud_Micro_Sec') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'SecDikeSM.Measures.measure_sandbagwall') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'ArnesEnvironmentSM.Other.DirtPile') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'PrimDikeSM.BreakTroughFX.WildWaterMesh') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'PrimDikeSM.MacroStab.MacroMeasure') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'PrimDikeSM.MacroStab.DykeFailureMain') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'PrimDikeSM.MacroStab.DykeFailureFront') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'PrimDikeSM.MacroStab.DykeFailureTop') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'PrimDikeSM.MacroStab.NonFailingDykePiece'); //if (skipmesh == false && self.LinkedTile.Mechanism != FM_Micro) if (skipmesh == false) { if ( (self.LinkedTile.Mechanism == FM_piping && OnlyVisibleIfActive.GraphActor[i].IsA('Emitter')) || (self.LinkedTile.Mechanism == FM_Macro && self.LinkedTile.LeveeType == LT_RegionalLevee)) { Log("Only visible if active: " @ OnlyVisibleIfActive.GraphActor[i].StaticMesh @ " - " @ (OnlyVisibleIfActive.GraphActor[i].OctreeBox.Min - OnlyVisibleIfActive.GraphActor[i].OctreeBox.Max) ); v = (OnlyVisibleIfActive.GraphActor[i].OctreeBox.Min); if (v.x != 0 && v.x < vMin.x) vMin.x = v.x; if (v.y != 0 && v.y < vMin.y) vMin.y = v.y; if (v.z != 0 && v.z < vMin.z) vMin.z = v.z; v = (OnlyVisibleIfActive.GraphActor[i].OctreeBox.Max); if (v.x != 0 && v.x > vMax.x) vMax.x = v.x; if (v.y != 0 && v.y > vMax.y) vMax.y = v.y; if (v.z != 0 && v.z > vMax.z) vMax.z = v.z; /// Also check location? /// If emitter, add some extra units based on the direction from the emitter - tile. offset = vect(1,1,1); offsetx = 1; offsety = 1; if (OnlyVisibleIfActive.GraphActor[i].IsA('Emitter')) { offset = (v - self.Linkedtile.Location); offset = Normal(offset); offsetx = offset.x * 640; offsety = offset.y * 640; Log("Offset emitter: " @ offset); } v = (OnlyVisibleIfActive.GraphActor[i].Location); //v *= offset; v.x += offsetx; v.y += offsety; if (v.x != 0 && v.x < vMin.x) vMin.x = v.x; if (v.y != 0 && v.y < vMin.y) vMin.y = v.y; if (v.z != 0 && v.z < vMin.z) vMin.z = v.z; if (v.x != 0 && v.x > vMax.x) vMax.x = v.x; if (v.y != 0 && v.y > vMax.y) vMax.y = v.y; if (v.z != 0 && v.z > vMax.z) vMax.z = v.z; } } } } else { /* for( i=0; i < OnlyVisibleIfNotActive.GraphActor.Length; i++ ) { skipmesh = (OnlyVisibleIfNotActive.GraphActor[i].StaticMesh == StaticMesh'SecDikeSM.MacroStab.SecMacroStabBase') || (OnlyVisibleIfNotActive.GraphActor[i].StaticMesh == StaticMesh'SecDikeSM.Measures.Measure_Berm_Macro_Sec') || (OnlyVisibleIfNotActive.GraphActor[i].StaticMesh == StaticMesh'PrimDikeSM.BreakTroughFX.WildWaterMeshPiping') || (OnlyVisibleIfNotActive.GraphActor[i].StaticMesh == StaticMesh'SecDikeSM.Measures.Measure_Talud_Micro_Sec') || (OnlyVisibleIfNotActive.GraphActor[i].StaticMesh == StaticMesh'SecDikeSM.Measures.measure_sandbagwall') || (OnlyVisibleIfActive.GraphActor[i].StaticMesh == StaticMesh'ArnesEnvironmentSM.Other.DirtPile'); // Log("Only visible if NOT active: " @ OnlyVisibleIfNotActive.GraphActor[i]); /// Test: spawn spheres to indicate which object is selected. //if (skipmesh == false) if (self.LinkedTile.Mechanism == FM_piping && OnlyVisibleIfActive.GraphActor[i].IsA('Emitter')) { v = (OnlyVisibleIfNotActive.GraphActor[i].OctreeBox.Min); //if (self.Linkedtile.Rotation.Yaw == 49158 || self.Linkedtile.Rotation.Yaw == -16384) //{ if (v.x != 0 && v.x < vMin.x) vMin.x = v.x; //} // if (self.Linkedtile.Rotation.Yaw == 32768) // { if (v.y != 0 && v.y < vMin.y) vMin.y = v.y; // } if (v.z != 0 && v.z < vMin.z) vMin.z = v.z; v = (OnlyVisibleIfNotActive.GraphActor[i].OctreeBox.Max); //if (self.Linkedtile.Rotation.Yaw == 49158 || self.Linkedtile.Rotation.Yaw == -16384) //{ if (v.x != 0 && v.x > vMax.x) vMax.x = v.x; //} //if (self.Linkedtile.Rotation.Yaw == 32768) //{ if (v.y != 0 && v.y > vMax.y) vMax.y = v.y; //} if (v.z != 0 && v.z > vMax.z) vMax.z = v.z; } } */ } /// Don't forget to include the static mesh when this object isn't active. v = (self.LinkedTile.OctreeBox.Min); if (v.x != 0 && v.x < vMin.x) vMin.x = v.x; if (v.y != 0 && v.y < vMin.y) vMin.y = v.y; if (v.z != 0 && v.z < vMin.z) vMin.z = v.z; v = (self.LinkedTile.OctreeBox.Max); if (v.x != 0 && v.x > vMax.x) vMax.x = v.x; if (v.y != 0 && v.y > vMax.y) vMax.y = v.y; if (v.z != 0 && v.z > vMax.z) vMax.z = v.z; if (ShowBoundingBoxes) { Log("Creating self debug mesh"); sMa = Spawn(class 'DynamicMeshActor'); sma.SetStaticMesh(StaticMesh'Editor.TexPropCube'); sma.SetCollision(false,false,false); } v.x = (abs(vMax.x - vMin.x) ) / 256; v.y = (abs(vMax.y - vMin.y) ) / 256; /// The dirty way. I just could not find a solution for it... switch (self.Linkedtile.Rotation.Yaw) { case 32768: rot.Yaw = self.Linkedtile.rotation.Yaw; // - 32768; sma.SetRotation(rot); break; case 49158: rot.Yaw = self.Linkedtile.rotation.Yaw - 16384; // + 16384; sma.SetRotation(rot); break; default: rot.Yaw = (self.Linkedtile.rotation.Yaw - 16384); // + 16384; sma.SetRotation(rot); break; } if (ShowBoundingBoxes) { v.z = 4; sma.SetDrawScale3D( v); v = self.LinkedTile.Location; // OnlyVisibleIfActive.GraphActor[i].location; v.x = (vMax.x + vMin.x)/2; v.y = (vMax.y + vMin.y)/2; v.z += 1024 * Frand(); sma.setLocation(v); ///temp: Log("Update indicators"); EncompassesVector(vect(0,0,0)); } } /// Use this, to get the unique ID of the failure. function name GetFailureName() { return LinkedTile.Name; } /// Kind of a hack to be able to create dynamic names for the various triggers. function name GetName(string NameString) { SetPropertyText("nTempName", NameString); return nTempName; } /// Add the given vector as offset from this objects location, and return it. function vector VectorOffset(vector offset) { return LinkedTile.Location + offset; } /// This function will add items to the "OnlyVisibleIfActive" array function AddToVIAList(actor oactor) { OnlyVisibleIfActive.GraphActor.Insert(VIACount,1); OnlyVisibleIfActive.GraphActor[VIACount] = oactor; //TEST - Almar 2007-10-02 Jln OnlyVisibleIfActive.GraphActor[VIACount].AmbientGlow = 10; VIACount++; } /// Calculate rotation, used in other functions. function vector CalculateOffset(vector center, float radius, float angle) { /// Relative position: local vector Loc; local rotator Rot; local float x; local float y; Loc = center; //Loction of the Orginal Vector Rot = LinkedTile.Rotation; //Rotation of the Orginal Rotator /// Add rotation of this tile to the angle. angle += (LinkedTile.Rotation.Yaw * URotToRadian); x = Loc.x + cos(angle)*radius; y = Loc.y + sin(angle)*radius; Loc.x = x; Loc.y = y; Loc.z = 300; //with hittest? return Loc; } /// Easy method of creating a dynamic mesh, saves a lot of code. function DynamicMeshActor CreateMesh(vector Location, string tag, StaticMesh meshname) { local DynamicMeshActor sMA; sMA = Spawn(class'DynamicMeshActor'); sMA.SetLocation(Location); //ok sMA.SetStaticMesh(meshname); sMA.SetPropertyText("Tag", tag); // Workaround, see below //sMA.SetRotation(LinkedTile.Rotation); sMA.AmbientGlow = 12; AddToVIAList(sMA); /// And return: return sMa; } function MeshMover CreateMeshMover(vector Location, string tag, StaticMesh meshname, float movetime, optional int numkeys) { local MeshMover M; M = Spawn(class'MeshMover'); M.SetLocation(Location); M.SetStaticMesh( meshname ); M.SetPropertyText("Tag", tag ); // Workaround, see below M.MoveTime = movetime * speedfactor; M.SetRotation(LinkedTile.Rotation); M.BaseRot = LinkedTile.Rotation; M.BasePos = Location; /// If there is a number of keys specified, update it as well: if (numkeys != 0) { M.SetNumKeys(numkeys); } M.AmbientGlow = 12; AddToVIAList(M); return M; } /// Create mover: function DynamicMover CreateMover(vector Location, string tag, StaticMesh meshname, float movetime, optional int numkeys) { local DynamicMover M; M = Spawn(class'DynamicMover'); M.SetLocation(Location); M.SetStaticMesh( meshname ); M.SetPropertyText("Tag", tag ); // Workaround, see below M.MoveTime = movetime * speedfactor; M.SetRotation(LinkedTile.Rotation); M.BaseRot = LinkedTile.Rotation; M.BasePos = Location; /// If there is a number of keys specified, update it as well: if (numkeys != 0) { M.SetNumKeys(numkeys); } M.AmbientGlow = 12; AddToVIAList(M); return M; } /// Create mover: function DynVariableTimedMover CreateVariableMover(vector Location, string tag, StaticMesh meshname, float movetime, optional int numkeys) { local DynVariableTimedMover M; M = Spawn(class'DynVariableTimedMover'); M.SetLocation(Location); M.SetStaticMesh( meshname ); M.SetPropertyText("Tag", tag ); // Workaround, see below M.MoveTime = movetime * speedfactor; M.AmbientGlow = 12; M.SetRotation(LinkedTile.Rotation); M.BaseRot = LinkedTile.Rotation; M.BasePos = Location; /// If there is a number of keys specified, update it as well: if (numkeys != 0) { M.SetNumKeys(numkeys); } AddToVIAList(M); return M; } /// Function to set all keys of a certain variable timed mover to the same value /// mover = mover to update /// movetime = time in seconds /// timestartindex = array start index /// timenum = amount of indices to set /// Same applies to movespeed. function SetDynamicMoverTime(DynVariableTimedMover Mv, float movetime, int timestartindex, int timenum, float movespeed, int speedstartindex, int speednum) { local int i; local int count; Mv.KeyMoveTime.Insert(timestartindex, timenum); Mv.KeyMoveSpeed.Insert(speedstartindex, speednum); /// Movetime: count = timestartindex+timenum; for (i = timestartindex; i < count; i++ ) { Mv.SetMoveTime(movetime * speedfactor, i); } /// Movespeed: count = speedstartindex+speednum; for (i = speedstartindex; i < count ; i++ ) { Mv.SetMoveSpeed(movespeed * speedfactor, i); } } /// Add/subtract pitch/yaw/roll from the current rotation, and update object function RotationOffset(Actor obj, Rotator original, int pitch, int yaw, int roll) { local Rotator r; r = original; r.Pitch += pitch; r.Yaw += yaw; r.Roll += roll; obj.SetRotation(r); if (Mover(obj) != None) { Mover(obj).BaseRot = r; } } /// Called when destroyed: event Destroyed() { Log("Destroying LeveeFailure"); } function vector RotateVector(float x, float y, float z, optional float extra) { local vector Loc; local float Yaw; Loc = LinkedTile.Location; //Loction of the Orginal Vector Yaw = (LinkedTile.Rotation.Yaw + RelativeRotation + extra) * URotToRadian ; /// Rotate vector based on object rotation and position Loc.X += x * cos(Yaw) - y * sin(Yaw); Loc.Y += x * sin(Yaw) + y * cos(Yaw); Loc.Z += z; // Loc.X += x * cos(Yaw) + y * sin(Yaw); // Loc.Y += -x * sin(Yaw) + y * cos(Yaw); // Loc.Z += z; return Loc; } function vector RotateVectorNoLocation(float x, float y, float z) { local vector Loc; local float Yaw; Loc = vect(0,0,0); //LinkedTile.Location; //Loction of the Orginal Vector Yaw = (LinkedTile.Rotation.Yaw + RelativeRotation) * URotToRadian ; /// Rotate vector based on object rotation and position Loc.X += x * cos(Yaw) - y * sin(Yaw); Loc.Y += x * sin(Yaw) + y * cos(Yaw); Loc.Z += z; return Loc; } function vector RotateVectorInvertRelative(float x, float y, float z) { local vector Loc; local float Yaw; Loc = LinkedTile.Location; //Loction of the Orginal Vector Yaw = (LinkedTile.Rotation.Yaw - RelativeRotation) * URotToRadian ; /// Rotate vector based on object rotation and position Loc.X += x * cos(Yaw) - y * sin(Yaw); Loc.Y += x * sin(Yaw) + y * cos(Yaw); Loc.Z += z; return Loc; } defaultproperties { /// Default mesh scale: (used in min/max calcs) MeshScale = 1.0 speedfactor = 1.0 FailureSize = TS_32M; }