public override void OnUpdate(int gameTime) { /* if (Parent == null) * { * Dispose(); * } * * else * {*/ _centerPos = Parent.Position + _offset; if (Math.Abs(_angle) > Math.PI * 2.0f) { _angle = 0.0f; } Ref.Position = _centerPos + MathEx.MultiplyVector(new Vector3(_radius * (float)Math.Cos(_angle), _radius * (float)Math.Sin(_angle), 0), _rotation); if (IsCloud) { _angle -= ScriptThread.GetVar <float>("vortexRotationSpeed") * 0.16f * Game.LastFrameTime; } else { _angle -= ScriptThread.GetVar <float>("vortexRotationSpeed") * _layerMask * Game.LastFrameTime; } // } base.OnUpdate(gameTime); }
// todo: Add crosswinds at vortex base w/ raycast public TornadoVortex(Vector3 initialPosition, bool neverDespawn) { _position = initialPosition; _createdTime = Game.GameTime; _lifeSpan = neverDespawn ? -1 : Probability.GetInteger(160000, 600000); _useInternalEntityArray = ScriptThread.GetVar <bool>("vortexUseEntityPool"); }
public override void OnUpdate(int gameTime) { if (ScriptThread.GetVar <bool>("vortexMovementEnabled")) { if (_position.DistanceTo(_player.Position) > 200.0f) { _destination = _player.Position.Around(50.0f); _destination.Z = World.GetGroundHeight(_destination) - 10.0f; } else if (_position.DistanceTo(_destination) < 15.0f) { _destination = Helpers.GetRandomPositionFromCoords(_position, 10.0f); _destination.Z = World.GetGroundHeight(_destination) - 10.0f; } _position = MathEx.MoveTowards(_position, _destination, ScriptThread.GetVar <float>("vortexMoveSpeedScale") * 0.287f); } float maxEntityDist = ScriptThread.GetVar <float>("vortexMaxEntityDist"); if (gameTime > _nextUpdateTime) { CollectNearbyEntities(maxEntityDist); _nextUpdateTime = gameTime + 800; } UpdatePulledEntities(gameTime, maxEntityDist); }
public override void OnUpdate(int gameTime) { if (ActiveVortexCount > 0 && Game.Player.IsDead && Function.Call <bool>(Hash.IS_SCREEN_FADED_OUT)) { RemoveAll(); } if (World.Weather == Weather.ThunderStorm && ScriptThread.GetVar <bool>("spawnInStorm")) { if (Game.GameTime - _lastSpawnAttempt > 1000) { if (Probability.GetBoolean(0.005f)) { Function.Call(Hash.SET_WIND_SPEED, 70.0f); var position = Game.Player.Character.Position + Game.Player.Character.ForwardVector * 100f; CreateVortex(position.Around(30f)); } _lastSpawnAttempt = Game.GameTime; } } base.OnUpdate(gameTime); }
private void OnKeyDown(object sender, ScriptEventArgs e) { var keyArgs = e.Data as KeyEventArgs; if (keyArgs == null) { return; } if (!ScriptThread.GetVar <bool>("enableconsole")) { return; } if (keyArgs.KeyCode == Keys.CapsLock) { _capsLock = !_capsLock; } if (!_showingConsole) { if (keyArgs.KeyCode == ScriptThread.GetVar <Keys>("toggleconsole")) { ShowConsole(); } } else { GetConsoleInput(keyArgs); } }
private void OnPlayerDead(Player sender, EventArgs e) { sender.RegisterDeaths(1); var scoreAmount = ScriptThread.GetVar <int>("scr_score_per_death"); RegisterTeamScore(sender.Info.Sess.TeamNum, scoreAmount.Value); var attackerEnt = Function.Call <Entity>(CustomNative.GET_PED_SOURCE_OF_DEATH, sender.Ped.Ref); if (attackerEnt != null) { ScriptMain.DebugPrint("OnPlayerDead: Found attacker entity."); var inflictor = current.Players .FirstOrDefault(x => x.PlayerRef.Ped == attackerEnt || x.PlayerRef.Vehicle == attackerEnt); if (inflictor.PlayerRef != null && sender.Info.Sess.TeamNum != inflictor.TeamIdx) { ScriptMain.DebugPrint("OnPlayerDead: Found inflicting player."); inflictor.PlayerRef.RegisterKills(1); scoreAmount = ScriptThread.GetVar <int>("scr_score_per_kill"); RegisterTeamScore(inflictor.TeamIdx, scoreAmount.Value); if (inflictor.PlayerRef is LocalPlayer) { displayMgr.ShowKillPopup(sender.Name, sender.Info.Sess.TeamNum); } } } // award assist points to players that inflicted damage.. for (int x = 0; x < current.NumPlayers; x++) { if (current.Players[x].TeamIdx == sender.Info.Sess.TeamNum) { continue; } if (sender.Vehicle.Ref.HasBeenDamagedBy(current.Players[x].PlayerRef.Ped) || sender.Vehicle.Ref.HasBeenDamagedBy(current.Players[x].PlayerRef.Vehicle)) { current.Players[x].PlayerRef.RegisterKills(1); scoreAmount = ScriptThread.GetVar <int>("scr_score_per_assist"); RegisterTeamScore(current.Players[x].TeamIdx, scoreAmount.Value); if (current.Players[x].PlayerRef is LocalPlayer) { displayMgr.ShowKillPopup(sender.Name, sender.Info.Sess.TeamNum); } } } }
private void UpdateDebrisLayer(materials material) { if (Game.GameTime - _lastDebrisSpawnTime > 3000 + Probability.GetInteger(0, 5000)) { // UI.ShowSubtitle("spawn debris"); new TDebris(this, _position, ScriptThread.GetVar <float>("vortexRadius")); } }
public void Build() { var layerSize = ScriptThread.GetVar <float>("vortexLayerSeperationScale").Value; var radius = ScriptThread.GetVar <float>("vortexRadius").Value; var particleCount = ScriptThread.GetVar <int>("vortexParticleCount").Value; var maxLayers = ScriptThread.GetVar <int>("vortexMaxParticleLayers"); var particleAsset = ScriptThread.GetVar <string>("vortexParticleAsset"); var particleName = ScriptThread.GetVar <string>("vortexParticleName"); var multiplier = 359 / particleCount; var particleSize = 3.0f; for (var i = 0; i < maxLayers; i++) { for (var angle = 0; angle <= particleCount; angle++) { // increment the Z axis as we build up. var position = _position; position.Z += layerSize * i; // place the particles at 360 / 10 on the X axis. var rotation = new Vector3(angle * multiplier, 0, 0); TornadoParticle particle; if (i < 2 || i > maxLayers - 3) { particle = new TornadoParticle(this, position, rotation, "scr_agencyheistb", "scr_env_agency3b_smoke", radius, i); particle.StartFx(4.7f); _particles.Add(particle); } particle = new TornadoParticle(this, position, rotation, particleAsset, particleName, radius, i); particle.StartFx(particleSize); radius += 0.0799999982118607f * (0.720000028610229f * i); particleSize += 0.00999999977648258f * (0.119999997317791f * i); _particles.Add(particle); } } }
string ResetVar(params string[] args) { if (args.Length < 1) { return("ResetVar: Invalid format."); } string varName = args[0]; int i; if (int.TryParse(args[1], out i)) { var foundVar = ScriptThread.GetVar <int>(varName); if (foundVar != null) { foundVar.Value = foundVar.Default; return(null); } } float f; if (float.TryParse(args[1], out f)) { var foundVar = ScriptThread.GetVar <float>(varName); if (foundVar != null) { foundVar.Value = foundVar.Default; return(null); } } bool b; if (bool.TryParse(args[1], out b)) { var foundVar = ScriptThread.GetVar <bool>(varName); if (foundVar != null) { foundVar.Value = foundVar.Default; return(null); } } return("Variable '" + args[0] + "' not found."); }
/// <summary> /// Instantiate the class. /// </summary> /// <param name="vortex"></param> /// <param name="fxAsset"></param> /// <param name="fxName"></param> /// <param name="position"></param> /// <param name="angle"></param> /// <param name="radius"></param> /// <param name="layerIdx"></param> public TornadoParticle(TornadoVortex vortex, Vector3 position, Vector3 angle, string fxAsset, string fxName, float radius, int layerIdx) : base(Setup(position)) { Parent = vortex; _centerPos = position; _rotation = MathEx.Euler(angle); _ptfx = new LoopedParticle(fxAsset, fxName); _radius = radius; _offset = new Vector3(0, 0, ScriptThread.GetVar <float>("vortexLayerSeperationScale") * layerIdx); LayerIndex = layerIdx; PostSetup(); }
private void PostSetup() { _layerMask = 1.0f - (float)LayerIndex / (ScriptThread.GetVar <int>("vortexMaxParticleLayers") * 4); _layerMask *= 0.1f * LayerIndex; _layerMask = 1.0f - _layerMask; if (_layerMask <= 0.3f) { _layerMask = 0.3f; } }
/// <summary> /// Setup world relationship groups. /// </summary> public void SetupRelationshipGroups() { int maxTeams = ScriptThread.GetVar <int>("scr_maxteams").Value; rGroups = Enumerable.Range(0, maxTeams) .Select(i => World.AddRelationshipGroup(string.Format("team{0}", i))).ToList(); foreach (int group in rGroups) { foreach (int enemyGroup in rGroups.Where(x => x != group)) { World.SetRelationshipBetweenGroups(Relationship.Hate, group, enemyGroup); } } }
private void InitSounds() { soundEnabled = ScriptThread.GetVar <bool>("soundenabled"); if (!soundEnabled) { return; } sirenEnabled = ScriptThread.GetVar <bool>("sirenenabled"); SoundLoad("tornado-weather-alert.wav", ref _tornadoWarningSiren, true); SoundLoad("rumble-bass-2.wav", ref _tornadoLowRumble, true); }
public static string SetVar(params string[] args) { if (args.Length < 2) { return("SetVar: Invalid format."); } var varName = args[0]; if (int.TryParse(args[1], out var i)) { var foundVar = ScriptThread.GetVar <int>(varName); if (foundVar != null) { return(!ScriptThread.SetVar(varName, i) ? "Failed to set the (integer) variable. Is it readonly?" : null); } } if (float.TryParse(args[1], out var f)) { var foundVar = ScriptThread.GetVar <float>(varName); if (foundVar != null) { return(!ScriptThread.SetVar(varName, f) ? "Failed to set the (float) variable. Is it readonly?" : null); } } if (bool.TryParse(args[1], out var b)) { var foundVar = ScriptThread.GetVar <bool>(varName); if (foundVar != null) { return(!ScriptThread.SetVar(varName, b) ? "Failed to set the (bool) variable. Is it readonly?" : null); } } return("Variable '" + args[0] + "' not found."); }
/// <summary> /// Create a vortex at the given position. /// </summary> /// <param name="position"></param> /// <returns></returns> public TornadoVortex CreateVortex(Vector3 position) { if (spawnInProgress) // tornado already spawning in { return(null); } for (var i = _activeVortexList.Length - 1; i > 0; i--) { _activeVortexList[i] = _activeVortexList[i - 1]; } position.Z = World.GetGroundHeight(position) - 10.0f; var tVortex = new TornadoVortex(position, false); tVortex.Build(); _activeVortexList[0] = tVortex; ActiveVortexCount = Math.Min(ActiveVortexCount + 1, _activeVortexList.Length); if (soundEnabled) { if (_tornadoLowRumble != null) { _tornadoLowRumble.SetVolume(0.0f); var volumeLevel = 1.0f - (1.0f / 300.0f * Vector3.Distance2D(position, GameplayCamera.Position)); volumeLevel = volumeLevel <0.0f ? 0.0f : volumeLevel> 1.0f ? 1.0f : volumeLevel; _tornadoLowRumble.DoFadeIn(5000, volumeLevel); } } if (ScriptThread.GetVar <bool>("notifications")) { UI.Notify("Tornado spawned nearby."); } spawnInProgress = true; return(null); }
/// <summary> /// Update the class. /// </summary> /// <param name="gameTime"></param> public override void OnUpdate(int gameTime) { if (!Game.IsScreenFadedOut) { dbgOutput.Update(); rankBar.Update(); if (ScriptThread.GetVar <bool>("scr_activesession").Value) { if (showScoreboard) { scoreboard.Draw(); } killPopup.Draw(); } if (showLeaderboard) { Function.Call(Hash.HIDE_HUD_AND_RADAR_THIS_FRAME); leaderboard.Draw(); if (Game.IsDisabledControlJustPressed(0, (Control)202) || Game.IsDisabledControlJustPressed(0, (Control)238)) { showLeaderboard = false; } if (Game.IsDisabledControlJustPressed(0, (Control)241) || Game.IsDisabledControlJustPressed(0, (Control)188)) { leaderboard.HandleScrollUp(); } else if (Game.IsDisabledControlJustPressed(0, (Control)242) || Game.IsDisabledControlJustPressed(0, (Control)187)) { leaderboard.HandleScrollDown(); } } } base.OnUpdate(gameTime); }
public override void OnUpdate(int gameTime) { if (!ScriptThread.GetVar <bool>("scr_hardcore").Value) { if (Game.IsControlJustPressed(0, Control.ScriptLB) || Game.IsControlJustPressed(0, (Control)48)) { var extinguisher = GetExtension <EngineExtinguisher>(); extinguisher.Start(); } else if (Game.IsControlJustPressed(0, Control.ScriptRB) || Game.IsControlJustPressed(0, (Control)337)) { var flareMgr = GetExtension <IRFlareManager>(); flareMgr.Start(); } } base.OnUpdate(gameTime); }
public override void OnUpdate(int gameTime) { if (gameTime - _createdTime > _lifeSpan) { _despawnRequested = true; } if (ScriptThread.GetVar <bool>("vortexEnableSurfaceDetection")) { UpdateSurfaceDetection(gameTime); } if (ScriptThread.GetVar <bool>("vortexMovementEnabled")) { if (_destination == Vector3.Zero || _position.DistanceTo(_destination) < 15.0f) { ChangeDestination(false); } if (_position.DistanceTo(_player.Position) > 200.0f) { ChangeDestination(true); } var vTarget = MathEx.MoveTowards(_position, _destination, ScriptThread.GetVar <float>("vortexMoveSpeedScale") * 0.287f); _position = Vector3.Lerp(_position, vTarget, Game.LastFrameTime * 20.0f); } float maxEntityDist = ScriptThread.GetVar <float>("vortexMaxEntityDist"); CollectNearbyEntities(gameTime, maxEntityDist); UpdatePulledEntities(gameTime, maxEntityDist); UpdateDebrisLayer(lastMaterialTraversed); // UpdateCrosswinds(gameTime); }
/// <summary> /// Create a vortex at the given position. /// </summary> /// <param name="position"></param> /// <returns></returns> public TornadoVortex CreateVortex(Vector3 position) { for (int i = _activeVortexList.Length - 1; i > 0; i--) { _activeVortexList[i] = _activeVortexList[i - 1]; } position.Z = World.GetGroundHeight(position) - 10.0f; var tVortex = new TornadoVortex(position); tVortex.Build(); _activeVortexList[0] = tVortex; ActiveVortexCount = Math.Min(ActiveVortexCount + 1, _activeVortexList.Length); if (ScriptThread.GetVar <bool>("notifications")) { UI.Notify("Tornado spawned nearby."); } return(tVortex); }
private void UpdatePulledEntities(float maxDistanceDelta) { float verticalForce = ScriptThread.GetVar <float>("vortexVerticalPullForce"); float horizontalForce = ScriptThread.GetVar <float>("vortexHorizontalPullForce"); float topSpeed = ScriptThread.GetVar <float>("vortexTopEntitySpeed"); for (var e = 0; e < _activeEntityCount; e++) { var entity = _activeEntities[e].Entity; var dist = Vector2.Distance(entity.Position.Vec2(), _position.Vec2()); if (dist > (maxDistanceDelta - 12.6f) || entity.HeightAboveGround > 300.0f) { RemoveEntity(e); continue; } var targetPos = new Vector3(_position.X + _activeEntities[e].XBias, _position.Y + _activeEntities[e].YBias, entity.Position.Z); var direction = Vector3.Normalize(targetPos - entity.Position); var forceBias = Probability.NextFloat(); var force = ForceScale * (forceBias + (forceBias / dist)); /* if (dist < InternalForcesDist) // if an entity is close enough to the center, eject them randomly out of the tornado... * { * direction = -direction; * * entity.ApplyForceToCenterOfMass(direction * force * 10.0f); * * var cross = Vector3.Cross(direction * force * 10.0f, Vector3.Cross(direction, entity.ForwardVector)); * * entity.ApplyForceToCenterOfMass(Vector3.Normalize(cross) * force); * * RemoveEntity(e); * * continue; * } * * else * {*/ if (entity.Handle == _player.Handle) // we won't update the player if there is something between them and the tornado... { var raycast = World.Raycast(entity.Position, targetPos, IntersectOptions.Map); if (raycast.DitHitAnything) { continue; } verticalForce *= 0.45f; horizontalForce *= 0.5f; } if (entity.Model.IsPlane) { force *= 6.0f; verticalForce *= 6.0f; } entity.ApplyForce(direction * horizontalForce, new Vector3(Probability.NextFloat(), 0, Probability.GetScalar())); // apply a directional force pulling them into the tornado... var upDir = Vector3.Normalize(new Vector3(_position.X, _position.Y, _position.Z + 1000.0f) - entity.Position); entity.ApplyForceToCenterOfMass(upDir * verticalForce); // apply vertical forces var cross = Vector3.Cross(direction, Vector3.WorldUp); //get a vector that is oriented horizontally relative to the vortex. entity.ApplyForceToCenterOfMass(Vector3.Normalize(cross) * force * horizontalForce); // move them along side the vortex. // } Function.Call(Hash.SET_ENTITY_MAX_SPEED, entity.Handle, topSpeed); } }
public override void OnUpdate(int gameTime) { base.OnUpdate(gameTime); var position = Player.Position; if (!ScriptThread.GetVar <bool>("scr_hardcore").Value) { if (Function.Call <bool>(Hash.IS_OBJECT_NEAR_POINT, 0x9A3207B7, position.X, position.Y, position.Z, (float)random.Next(50, 200)) && position.DistanceTo(GameplayCamera.Position) < 700.0f && !flareMgr.CooldownActive && Probability.GetBoolean(0.0020f + intelligenceBias)) { flareMgr.Start(); } /*( if (Player.Vehicle.Ref.Health < Player.Vehicle.Ref.MaxHealth && * !extinguisher.CooldownActive && * Probability.GetBoolean(intelligenceBias) ) * { * ScriptMain.DebugPrint("use extinguisher (" + Name + ")"); * extinguisher.Start(); * }*/ } if (gameTime > state.NextDecisionTime) { // If we arent chasing a target, they have moved too far away, or have been chasing a target for a set amount of time, make a new decision. if (Player.ActiveTarget == null || Player.ActiveTarget.Ped.Ref.IsDead || position.DistanceTo(Player.ActiveTarget.Position) > 1000.0f || !Utility.IsPositionInArea(Player.ActiveTarget.Position, levelMgr.Level.Bounds.Min, levelMgr.Level.Bounds.Max) || Game.GameTime - attackStartedTime > 30000) { MakeDecision(); } state.SetNextDecisionTime(gameTime + random.Next(1000, 5000)); } switch (state.Status) { case AIStatus.FightOther: { if (Player.ActiveTarget != null) { if (Player.ActiveTarget.Position.DistanceTo(Player.Position) > 600.0f) { if (!tooFar) { var destination = Player.ActiveTarget.Position; Function.Call(Hash.TASK_PLANE_MISSION, Player.Ped.Ref, Player.Vehicle.Ref, 0, 0, destination.X, destination.Y, destination.Z, 6, 309.0, 26.0f, 200.0, 1000.0, 20.0); tooFar = true; } } else if (Function.Call <int>(Hash.GET_ACTIVE_VEHICLE_MISSION_TYPE, Player.Vehicle.Ref) != 6) { tooFar = false; Player.PersueTarget(Player.ActiveTarget); UI.ShowSubtitle("persuing " + Function.Call <int>(Hash.GET_ACTIVE_VEHICLE_MISSION_TYPE, Player.Vehicle.Ref).ToString()); } } break; } case AIStatus.RandomFlight: { if (position.DistanceTo(destination) < 15.0f) { SetRandomDestination(); ScriptMain.DebugPrint("Set new random destination for " + Player.Name); } else if (Player.Position.DistanceTo(sessionMgr.Current.Players[0].PlayerRef.Position) < 1000.0f && Player.Info.Sess.TeamNum != sessionMgr.Current.Players[0].TeamIdx) { Player.PersueTarget(sessionMgr.Current.Players[0].PlayerRef); state.Status = AIStatus.FightOther; } break; } } for (int i = 0; i < sessionMgr.Current.NumPlayers; i++) { if (gameTime - lastShotAtTime > 900) { var otherPlayer = sessionMgr.Current.Players[i]; if (otherPlayer.TeamIdx == Player.Info.Sess.TeamNum) { continue; } var p = otherPlayer.PlayerRef.Position; var direction = Vector3.Normalize(p - position); var otherHeading = otherPlayer.PlayerRef.Vehicle.Ref.Heading; if (Probability.GetBoolean(0.1f + intelligenceBias) && position.DistanceTo(p) < 400.0f) { Function.Call(Hash.SET_VEHICLE_SHOOT_AT_TARGET, Player.Ped.Ref, otherPlayer.PlayerRef.Vehicle.Ref, p.X, p.Y, p.Z); ScriptMain.DebugPrint("Shoot at target (" + Player.Name + " > " + otherPlayer.PlayerRef.Name + ") team idx:" + otherPlayer.PlayerRef.Info.Sess.TeamNum.ToString() + " sess team:" + otherPlayer.TeamIdx); lastShotAtTime = gameTime; } } } }
public override void OnUpdate(int gameTime) { var parentPos = parent.Position; float dist = Vector2.Distance(Ref.Position.Vec2(), parentPos.Vec2()); if (dist > parent.MaxEntityDist || Ref.HeightAboveGround > 300.0f) { Dispose(); } else { var direction = Vector3.Normalize(new Vector3(parentPos.X, parentPos.Y, Ref.Position.Z) - Ref.Position); if (dist < parent.InternalForcesDist) { direction = -direction; Ref.ApplyForceToCenterOfMass(direction * 2.0f); var cross = Vector3.Cross(direction * 2.0f, Vector3.Cross(direction, Ref.ForwardVector)); Ref.ApplyForceToCenterOfMass(Vector3.Normalize(cross)); Dispose(); } else { var upDir = Vector3.Normalize(new Vector3(parentPos.X, parentPos.Y, parentPos.Z + 1000.0f) - Ref.Position); Ref.ApplyForce(direction, new Vector3(Probability.NextFloat(), Probability.NextFloat(), Probability.NextFloat())); Ref.ApplyForceToCenterOfMass(direction * parent.ForceScale * (ScriptThread.GetVar <float>("vortexHorzizontalPullForce") / dist)); Ref.ApplyForceToCenterOfMass(upDir * ScriptThread.GetVar <float>("vortexVerticalPullForce") * (2.0f / dist)); var cross = Vector3.Cross(direction, Vector3.WorldUp); float forceBias = Probability.NextFloat(); Ref.ApplyForceToCenterOfMass(Vector3.Normalize(cross) * parent.ForceScale * (((forceBias * 0.6f) + 0.16f) + (forceBias / dist))); // move them horizontally relative to the vortex. if (Probability.GetBoolean(0.23f)) { Ref.ApplyForceToCenterOfMass(direction * parent.ForceScale); cross = Vector3.Cross(direction, Vector3.Cross(direction, Ref.ForwardVector)); Ref.ApplyForceToCenterOfMass(Vector3.Normalize(cross) * parent.ForceScale); } if (Ref is Ped && Ref.Handle != Game.Player.Character.Handle && !(Ref as Ped).IsRagdoll) { Function.Call(Hash.SET_PED_TO_RAGDOLL, Ref.Handle, 800, 1500, 2, 1, 1, 0); } } Function.Call(Hash.SET_ENTITY_MAX_SPEED, Ref.Handle, 30.0f); } base.OnUpdate(gameTime); }
private void UpdatePulledEntities(int gameTime, float maxDistanceDelta) { float verticalForce = ScriptThread.GetVar <float>("vortexVerticalPullForce"); float horizontalForce = ScriptThread.GetVar <float>("vortexHorizontalPullForce"); float topSpeed = ScriptThread.GetVar <float>("vortexTopEntitySpeed"); pendingRemovalEntities.Clear(); foreach (var e in _pulledEntities) { var entity = e.Value.Entity; var dist = Vector2.Distance(entity.Position.Vec2(), _position.Vec2()); if (dist > maxDistanceDelta - 13f || entity.HeightAboveGround > 300.0f) { ReleaseEntity(e.Key); continue; } var targetPos = new Vector3(_position.X + e.Value.XBias, _position.Y + e.Value.YBias, entity.Position.Z); var direction = Vector3.Normalize(targetPos - entity.Position); var forceBias = Probability.NextFloat(); var force = ForceScale * (forceBias + forceBias / dist); if (e.Value.IsPlayer) { verticalForce *= 1.62f; horizontalForce *= 1.2f; // horizontalForce *= 1.5f; if (gameTime - _lastPlayerShapeTestTime > 1000) { var raycast = World.Raycast(entity.Position, targetPos, IntersectOptions.Map); _lastRaycastResultFailed = raycast.DitHitAnything; _lastPlayerShapeTestTime = gameTime; } if (_lastRaycastResultFailed) { continue; } } if (entity.Model.IsPlane) { force *= 6.0f; verticalForce *= 6.0f; } // apply a directional force pulling them into the tornado... entity.ApplyForce(direction * horizontalForce, new Vector3(Probability.NextFloat(), 0, Probability.GetScalar())); var upDir = Vector3.Normalize(new Vector3(_position.X, _position.Y, _position.Z + 1000.0f) - entity.Position); // apply vertical forces entity.ApplyForceToCenterOfMass(upDir * verticalForce); var cross = Vector3.Cross(direction, Vector3.WorldUp); // move them along side the vortex. entity.ApplyForceToCenterOfMass(Vector3.Normalize(cross) * force * horizontalForce); Function.Call(Hash.SET_ENTITY_MAX_SPEED, entity.Handle, topSpeed); } foreach (var e in pendingRemovalEntities) { _pulledEntities.Remove(e); } }
public void Build() { float radius = ScriptThread.GetVar <float>("vortexRadius"); int particleCount = ScriptThread.GetVar <int>("vortexParticleCount"); int maxLayers = ScriptThread.GetVar <int>("vortexMaxParticleLayers"); string particleAsset = ScriptThread.GetVar <string>("vortexParticleAsset"); string particleName = ScriptThread.GetVar <string>("vortexParticleName"); bool enableClouds = ScriptThread.GetVar <bool>("vortexEnableCloudTopParticle"); bool enableDebris = ScriptThread.GetVar <bool>("vortexEnableCloudTopParticleDebris"); var multiplier = 360 / particleCount; var particleSize = 3.0685f; maxLayers = enableClouds ? 12 : maxLayers; // cannot spawn top particles with more than 12 layers!! for (var layerIdx = 0; layerIdx < maxLayers; layerIdx++) { //var lyrParticleNum = (i > maxLayers - 4 ? particleCount + 5 : particleCount); //multiplier = 360 / lyrParticleNum; for (var angle = 0; angle < (layerIdx > maxLayers - 4 ? particleCount + 5 : particleCount); angle++) { // increment the Z axis as we build up. var position = _position; position.Z += ScriptThread.GetVar <float>("vortexLayerSeperationScale") * layerIdx; // place the particles at 360 / 10 on the X axis. var rotation = new Vector3(angle * multiplier, 0, 0); TornadoParticle particle; bool bIsTopParticle = false; if (layerIdx < 2) //debris layer { particle = new TornadoParticle(this, position, rotation, "scr_agencyheistb", "scr_env_agency3b_smoke", radius, layerIdx); particle.StartFx(4.7f); _particles.Add(particle); Function.Call(Hash.ADD_SHOCKING_EVENT_FOR_ENTITY, 86, particle.Ref.Handle, 0.0f); // shocking event at outer vorticies } if (enableClouds && layerIdx > maxLayers - 3) { if (enableDebris) { particle = new TornadoParticle(this, position, rotation, "scr_agencyheistb", "scr_env_agency3b_smoke", radius * 2.2f, layerIdx); particle.StartFx(12.7f); _particles.Add(particle); } position.Z += 12f; particleSize += 6.0f; radius += 7f; bIsTopParticle = true; } particle = new TornadoParticle(this, position, rotation, particleAsset, particleName, radius, layerIdx, bIsTopParticle); particle.StartFx(particleSize); radius += 0.0799999982118607f * (0.720000028610229f * layerIdx); particleSize += 0.00999999977648258f * (0.119999997317791f * layerIdx); _particles.Add(particle); } } }
public override void OnUpdate(int gameTime) { //UI.ShowSubtitle("vcount: " + ActiveVortexCount + " spawning: " + spawnInProgress + " delay spawn: " + delaySpawn); if (ActiveVortexCount < 1) { if (World.Weather == Weather.ThunderStorm && ScriptThread.GetVar <bool>("spawnInStorm")) { if (!spawnInProgress && Game.GameTime - _lastSpawnAttempt > 1000) { if (Probability.GetBoolean(0.05f)) { _spawnDelayStartTime = Game.GameTime; _spawnDelayAdditive = Probability.GetInteger(0, 40); Function.Call(Hash.SET_WIND_SPEED, 70.0f); // add suspense :p if (soundEnabled && sirenEnabled && _tornadoWarningSiren != null) { _tornadoWarningSiren.SetVolume(0.6f); _tornadoWarningSiren.Play(true); } if (ScriptThread.GetVar <bool>("notifications")) { Helpers.NotifyWithIcon("Severe Weather Alert", "Tornado Warning issued for Los Santos and Blaine County", "char_milsite"); } spawnInProgress = true; delaySpawn = true; } _lastSpawnAttempt = Game.GameTime; } } else { delaySpawn = false; } if (delaySpawn) { // UI.ShowSubtitle("current: " + (Game.GameTime - _spawnDelayStartTime) + " target: " + (TornadoSpawnDelayBase + _spawnDelayAdditive)); if (Game.GameTime - _spawnDelayStartTime > (TornadoSpawnDelayBase + _spawnDelayAdditive)) { spawnInProgress = false; delaySpawn = false; var position = Game.Player.Character.Position + Game.Player.Character.ForwardVector * 100f; CreateVortex(position.Around(150.0f).Around(175.0f)); } } } else { if (_activeVortexList[0].DespawnRequested || Game.Player.IsDead && Function.Call <bool>(Hash.IS_SCREEN_FADED_OUT)) { RemoveAll(); } else if (soundEnabled) { if (_tornadoLowRumble != null) { var distance = Vector3.Distance2D(_activeVortexList[0].Position, GameplayCamera.Position); //attenuation factor var volumeLevel = 1.0f - 1.0f / 800.0f * distance; if (distance < 170.0f) { volumeLevel += 0.087f * (2.219f * volumeLevel); } volumeLevel = volumeLevel <0.0f ? 0.0f : volumeLevel> 1.0f ? 1.0f : volumeLevel; _tornadoLowRumble.SetVolume(volumeLevel); } } } base.OnUpdate(gameTime); }