private bool IsValidCharacter(IMyCharacter character) { if (character != null) { if (!TargetCharacters || character.IsDead) // dont target if not set or dead { return(false); } IMyPlayer player = MyAPIGateway.Players.GetPlayerControllingEntity(character); if (player == null) { return(false); } MyRelationsBetweenPlayerAndBlock relation = player.GetRelationTo(CubeBlock.OwnerId); if (!(relation == MyRelationsBetweenPlayerAndBlock.Enemies || TargetNeutrals && (relation == MyRelationsBetweenPlayerAndBlock.Neutral || relation == MyRelationsBetweenPlayerAndBlock.NoOwnership))) { return(false); } return(true); } return(false); }
/// <summary> /// Handles the damage in ProtectionAreas if Protection is enabled. This method is desinged for server side use and will notify the players if they tried to damage the wrong block. /// </summary> /// <param name="target"></param> /// <param name="info"></param> private static void DamageHandler_Server(object target, ref MyDamageInformation info) { if (!Config.ProtectionEnabled) { return; } IMySlimBlock block = target as IMySlimBlock; if (block != null) { IMyPlayer player; if (CanDamageBlock(info.AttackerId, block, info.Type, out player)) { return; } info.Amount = 0; // notify player DateTime time; if (player != null && (!_sentFailedMessage.TryGetValue(player, out time) || DateTime.Now - time >= TimeSpan.FromMilliseconds(GrindFailedMessageInterval))) { MessageClientNotification.SendMessage(player.SteamUserId, "You are not allowed to damage this block.", GrindFailedMessageInterval, MyFontEnum.Red); _sentFailedMessage.Update(player, DateTime.Now); } return; } // disable pvp in PAs IMyCharacter character = target as IMyCharacter; if (character != null) { var players = new List <IMyPlayer>(); MyAPIGateway.Players.GetPlayers(players, p => p != null && p.Controller.ControlledEntity != null && p.Controller.ControlledEntity.Entity != null); var player = players.FirstOrDefault(p => p.GetCharacter() == character); if (player == null) { return; } if (!IsProtected(player.Controller.ControlledEntity.Entity)) { return; } if (info.Type == MyDamageType.LowPressure || info.Type == MyDamageType.Asphyxia || info.Type == MyDamageType.Environment || info.Type == MyDamageType.Fall || info.Type == MyDamageType.Fire || info.Type == MyDamageType.Radioactivity || info.Type == MyDamageType.Suicide || info.Type == MyDamageType.Unknown) { return; } info.Amount = 0; } }
private IMyPlayer FindPlayer(IMyEngineerToolBase handTool) { List <IMyPlayer> players = new List <IMyPlayer>(); MyAPIGateway.Players.GetPlayers(players); foreach (IMyPlayer player in players) { IMyCharacter character = player.Controller.ControlledEntity as IMyCharacter; if (character == null) { continue; } // The most inefficient way of finding which player is equiped with what tool. // What is needed is either MyCharacter.CurrentWeapon, or MyEngineerToolBase.Owner exposed through the appropriate interface. MyObjectBuilder_Character c = character.GetObjectBuilder(true) as MyObjectBuilder_Character; if (c != null && c.HandWeapon != null && c.HandWeapon.EntityId == handTool.EntityId) { return(player); } } return(null); }
private IMyEntity GridStandingOn(IMyCharacter character) { var GROUND_SEARCH = 2; var pos = character.PositionComp.GetPosition(); var worldRef = character.PositionComp.WorldMatrixRef; rays_cache_.Clear(); ray_tracer_.Hits.Clear(); var up = pos + worldRef.Up * 0.5; var down = up + worldRef.Down * GROUND_SEARCH; var forward = worldRef.Forward * 0.2; var back = -forward; GenerateRays(up, down, forward, back); var hits = ray_tracer_.CastRays(rays_cache_); var validHit = hits.FirstOrDefault(h => h != null && h.HitEntity != null && h.HitEntity != ((IMyCameraController)character).Entity.Components); if (validHit != null) { var entity = validHit.HitEntity.GetTopMostParent(); if (Vector3D.DistanceSquared(validHit.Position, up) < (double)GROUND_SEARCH * GROUND_SEARCH) { return(entity); } } return(null); }
/// <summary> /// if necessary, builds script for an entity /// </summary> /// <param name="entity"></param> private void Entities_OnEntityAdd(IMyEntity entity) { IMyCubeGrid asGrid = entity as IMyCubeGrid; if (asGrid != null) { List <IMySlimBlock> blocksInGrid = new List <IMySlimBlock>(); asGrid.GetBlocks(blocksInGrid, slim => slim.FatBlock != null); foreach (IMySlimBlock slim in blocksInGrid) { Grid_OnBlockAdded(slim); } asGrid.OnBlockAdded += Grid_OnBlockAdded; asGrid.OnClosing += Grid_OnClosing; foreach (var constructor in GridScriptConstructors) { constructor.Invoke(asGrid); } return; } IMyCharacter asCharacter = entity as IMyCharacter; if (asCharacter != null) { foreach (var constructor in CharacterScriptConstructors) { constructor.Invoke(asCharacter); } return; } }
/// <summary> /// Tries to create a radio component for an entity. Creates the radio component if the entity is a radio antenna block, beacon block, or a character. /// </summary> /// <param name="obj">Entity to create the component for.</param> /// <returns>A new radio component for the entity, if it can be created. Null, otherwise.</returns> public static ComponentRadio TryCreateRadio(IMyEntity obj) { IMyRadioAntenna radioAnt = obj as IMyRadioAntenna; if (radioAnt != null) { return(new CR_AntennaBlock(radioAnt)); } IMyBeacon beacon = obj as IMyBeacon; if (beacon != null) { return(new CR_BeaconBlock(beacon)); } IMyCharacter character = obj as IMyCharacter; if (character != null) { return(new CR_Character(character)); } return(null); }
public Character(IMyEntity entity) : base(entity) { Log.ClassName = "GP.Concealment.World.Entities.Character"; Log.Trace("New Character " + Entity.EntityId + " " + DisplayName, "ctr"); CharacterEntity = Entity as IMyCharacter; }
void DrawPaletteHUD() { PlayerInfo localInfo = Main.Palette.LocalInfo; if (localInfo == null) { return; } if (Main.LocalToolHandler.LocalTool != null && !MyAPIGateway.Gui.IsCursorVisible && !(Main.Settings.hidePaletteWithHUD && Main.GameConfig.HudState == HudState.OFF)) { MatrixD camMatrix = MyAPIGateway.Session.Camera.WorldMatrix; float scaleFOV = (Main.DrawUtils.ScaleFOV * Main.Settings.paletteScale); IMyCharacter character = MyAPIGateway.Session.Player.Character; if (Utils.IsAimingDownSights(character)) { MyTransparentGeometry.AddPointBillboard(MATERIAL_DOT, Color.Lime, camMatrix.Translation + camMatrix.Forward * LocalToolHandler.PAINT_AIM_START_OFFSET, 0.005f, 0, blendType: AIM_DOT_BLEND_TYPE); } Vector3D worldPos = Main.DrawUtils.HUDtoWorld(Main.Settings.paletteScreenPos); float bgAlpha = (Main.Settings.paletteBackgroundOpacity < 0 ? Main.GameConfig.HudBackgroundOpacity : Main.Settings.paletteBackgroundOpacity); DrawColorSelector(camMatrix, worldPos, scaleFOV, bgAlpha); DrawSkinSelector(camMatrix, worldPos, scaleFOV, bgAlpha); } }
public static byte[] SerializeAndSign(IMyCubeGrid grid, IMyPlayer player, Vector3I block) { var c = grid.GetCubeBlock(block)?.FatBlock as IMyCockpit; IMyCharacter pilot = c?.Pilot; c?.RemovePilot(); var ob = (MyObjectBuilder_CubeGrid)grid.GetObjectBuilder(); if (pilot != null) { c.AttachPilot(pilot); } IMyFaction fac = MyAPIGateway.Session.Factions.TryGetPlayerFaction(player.IdentityId); var data = new ClientData(ob, fac, block, Settings.Instance.HubIP); string obStr = MyAPIGateway.Utilities.SerializeToXML(data); string totalStr = DateTime.UtcNow.Ticks + obStr; string evalStr = totalStr + Settings.Instance.Password; var m = new MD5(); m.Value = evalStr; totalStr += m.FingerPrint; return(Encoding.UTF8.GetBytes(totalStr)); }
/// <summary> /// if necessary, builds script for an entity /// </summary> /// <param name="entity"></param> private void AddEntity(IMyEntity entity) { // the save flag is often on initially and disabled after if (!(entity.Save || entity is IMyCharacter)) { return; } IMyCubeGrid asGrid = entity as IMyCubeGrid; if (asGrid != null) { List <IMySlimBlock> blocksInGrid = new List <IMySlimBlock>(); asGrid.GetBlocks(blocksInGrid, slim => slim.FatBlock != null); foreach (IMySlimBlock slim in blocksInGrid) { AddBlock(slim); } asGrid.OnBlockAdded += Grid_OnBlockAdded; asGrid.OnClosing += Grid_OnClosing; foreach (var constructor in GridScriptConstructors) { try { constructor.Invoke(asGrid); } catch (Exception ex) { Log.AlwaysLog("Exception in grid constructor: " + ex, Logger.severity.ERROR); Logger.DebugNotify("Exception in grid constructor", 10000, Logger.severity.ERROR); } } return; } IMyCharacter asCharacter = entity as IMyCharacter; if (asCharacter != null) { if (!Characters.Add(entity.EntityId)) { return; } entity.OnClosing += alsoChar => { if (Characters != null) { Characters.Remove(alsoChar.EntityId); } }; Log.DebugLog("adding character: " + entity.getBestName()); foreach (var constructor in CharacterScriptConstructors) { try { constructor.Invoke(asCharacter); } catch (Exception ex) { Log.AlwaysLog("Exception in character constructor: " + ex, Logger.severity.ERROR); Logger.DebugNotify("Exception in character constructor", 10000, Logger.severity.ERROR); } } return; } }
public void FixShipModLookedAt() { if (Context.Player == null) { Context.Respond("Console has no Character so cannot use this command. Use !fixshipmod <Gridname> instead!"); return; } IMyCharacter character = Context.Player.Character; if (character == null) { Context.Respond("You have no Character currently. Make sure to spawn and be out of cockpit!"); return; } var steamId = new SteamIdCooldownKey(PlayerUtils.GetSteamId(Context.Player)); if (!CheckConformation(steamId, 0, "nogrid", character)) { return; } try { var result = ShipFixerCore.Instance.FixShip(character, 0); WriteResponse(result); } catch (Exception e) { Log.Error(e, "Error on fixing ship"); } }
/// <summary> /// Register character events. /// </summary> /// <param name="character">The character.</param> private void RegisterEvents(IMyCharacter character) { if (character != null) { character.MovementStateChanged += OnMovementStateChanged; } }
public bool Confirm(long cost, ulong steamid) { IMyPlayer player = Context.Player; long playerId; if (player == null) { Context.Respond("Console cannot use this command!"); return(false); } else { playerId = player.IdentityId; } IMyCharacter character = player.Character; if (character == null) { Context.Respond("You have no Character currently. Make sure to spawn and be out of cockpit!"); return(false); } var currentCooldownMap = Plugin.CurrentCooldownMapCommand; if (currentCooldownMap.TryGetValue(steamid, out CurrentCooldown currentCooldown)) { long remainingSeconds = currentCooldown.GetRemainingSeconds(null); if (remainingSeconds > 0) { Log.Info("Cooldown for Player " + player.DisplayName + " still running! " + remainingSeconds + " seconds remaining!"); Context.Respond("Command is still on cooldown for " + remainingSeconds + " seconds."); return(false); } currentCooldown = CreateNewCooldown(currentCooldownMap, steamid, Plugin.Cooldown); } else { currentCooldown = CreateNewCooldown(currentCooldownMap, steamid, Plugin.Cooldown); } if (!CheckConformation(cost, steamid, Context.Player.DisplayName)) { return(false); } try { Log.Info("Cooldown for Player " + player.DisplayName + " started!"); currentCooldown.StartCooldown(null); return(true); } catch (Exception e) { Log.Error(e); return(false); } }
public List <RayCastResult> CastRaysAroundPlayer(IMyCharacter character, double distance, int raysCount) { var position = character.GetPosition(); var orientation = character.PositionComp.GetOrientation(); var forward = orientation.Forward; return(CastRaysAroundPosition(position + orientation.Up, forward, distance, raysCount)); }
public virtual void Init(IMyCharacter character, Dictionary<MyStringHash, MyEntityStat> stats, string scriptName) { m_scriptName = scriptName; Character = character; m_stats = stats; InitSettings(); }
public virtual void Init(IMyCharacter character, Dictionary <MyStringHash, MyEntityStat> stats, string scriptName) { m_scriptName = scriptName; Character = character; m_stats = stats; InitSettings(); }
public static IMyInventory GetPlayerInventory(this IMyCharacter character) { if (character == null) { return(null); } return(((MyEntity)character).GetInventory()); }
/// <summary> /// Gets a name for an entity that can be shown to players. Assumes the entity has been detected in a fair way. /// </summary> /// <param name="entity">The entity to get the name for.</param> /// <param name="playerId">Who wants to know?</param> /// <returns>A name that can be shown to players.</returns> public static string GetNameForDisplay(this IMyEntity entity, long playerId) { IMyCubeGrid asGrid = entity as IMyCubeGrid; if (asGrid != null) { if (playerId.canConsiderFriendly(asGrid)) { return(asGrid.DisplayName); } else { return(asGrid.SimpleName()); } } IMyCubeBlock asBlock = entity as IMyCubeBlock; if (asBlock != null) { if (playerId.canConsiderFriendly(asBlock.OwnerId)) { return(asBlock.DisplayNameText + " on " + GetNameForDisplay(asBlock.CubeGrid, playerId)); } else { return(asBlock.DefinitionDisplayNameText + " on " + GetNameForDisplay(asBlock.CubeGrid, playerId)); } } IMyCharacter asChar = entity as IMyCharacter; if (asChar != null) { if (string.IsNullOrEmpty(entity.DisplayName)) { return("Creature"); } return(entity.DisplayName); } if (entity is IMyVoxelMap) { return("Asteroid"); } if (entity is MyPlanet) { return("Planet"); } if (entity.IsMissile()) { return("Missile"); } return(entity.getBestName()); }
public static Relations getRelationsTo(this long identityId, IMyEntity target, Relations breakOn = Relations.NoOwner) { if (identityId == 0L) { return(Relations.NoOwner); } IMyCubeBlock asBlock = target as IMyCubeBlock; if (asBlock != null) { return(getRelationsTo(identityId, asBlock.OwnerId)); } IMyCubeGrid asGrid = target as IMyCubeGrid; if (asGrid != null) { return(getRelationsTo(identityId, asGrid, breakOn)); } IMyCharacter asChar = target as IMyCharacter; if (asChar != null) { if (asChar.IsBot) { return(Relations.Enemy); } IMyPlayer player = asChar.GetPlayer_Safe(); if (player != null) { return(getRelationsTo(identityId, player.IdentityId)); } Logger.DebugLog("character not found, treating as enemy: " + target.getBestName(), Logger.severity.WARNING); return(Relations.Enemy); } if (target is IMyMeteor) { return(Relations.Enemy); } if (target.IsMissile()) { long missileOwner; if (GuidedMissile.TryGetOwnerId(target.EntityId, out missileOwner)) { return(getRelationsTo(identityId, missileOwner)); } return(Relations.Enemy); } Logger.DebugLog("unknown entity, treating as enemy: " + target.getBestName(), Logger.severity.WARNING); return(Relations.Enemy); }
/// <summary> /// Show a 'fuel low' warning. /// </summary> private static void ShowFuelLowWarningNotification(IMyCharacter character) { var soundEmitter = new MyEntity3DSoundEmitter((MyEntity)character); var pair = new MySoundPair("ArcHudVocFuelLow"); soundEmitter.PlaySingleSound(pair); MyAPIGateway.Utilities.ShowNotification(MyTexts.GetString(MySpaceTexts.NotificationFuelLow), 2500, "Red"); }
public static float GetH2Level(this IMyCharacter character) { MyCharacterOxygenComponent comp; if (!character.Components.TryGet(out comp)) { return(0); } return(comp.GetGasFillLevel(MyCharacterOxygenComponent.HydrogenId)); }
public static float GetO2Level(this IMyCharacter character) { MyCharacterOxygenComponent comp; if (!character.Components.TryGet(out comp)) { return(0); } return(comp.SuitOxygenLevel); }
/// <summary> /// Calculates alignment to given gravity. /// </summary> /// <param name="character">The character for which this is calculated.</param> /// <param name="gravity">The gravity vector.</param> /// <param name="up">The up vector.</param> /// <param name="forward">The forward vector.</param> private static void CalculateAlignment(IMyCharacter character, ref Vector3 gravity, ref Vector3 up, ref Vector3 forward) { var invertedNormalizedGravity = -Vector3.Normalize(gravity); var direction = invertedNormalizedGravity; if (character.Physics != null) { var supportNormal = character.Physics.SupportNormal; var definition = character.Definition as MyCharacterDefinition; if (definition != null) { if (definition.RotationToSupport == MyEnumCharacterRotationToSupport.OneAxis) { var num1 = invertedNormalizedGravity.Dot(ref supportNormal); if (!MyUtils.IsZero(num1 - 1f) && !MyUtils.IsZero(num1 + 1f)) { var cross = invertedNormalizedGravity.Cross(supportNormal); cross.Normalize(); direction = Vector3.Lerp(supportNormal, invertedNormalizedGravity, Math.Abs(cross.Dot(character.WorldMatrix.Forward))); } } else if (definition.RotationToSupport == MyEnumCharacterRotationToSupport.Full) { direction = supportNormal; } } } var dot = Vector3.Dot(up, direction) / (up.Length() * direction.Length()); if (float.IsNaN(dot) || float.IsNegativeInfinity(dot) || float.IsPositiveInfinity(dot)) { dot = 1f; } dot = MathHelper.Clamp(dot, -1f, 1f); if (MyUtils.IsZero(dot - 1f, 1E-08f)) { return; } var angle = !MyUtils.IsZero(dot + 1f, 1E-08f) ? (float)Math.Acos(dot) : 0.1f; angle = Math.Min(Math.Abs(angle), 0.04f) * Math.Sign(angle); var axis = Vector3.Cross(up, direction); if (axis.LengthSquared() <= 0.0) { return; } axis = Vector3.Normalize(axis); up = Vector3.TransformNormal(up, Matrix.CreateFromAxisAngle(axis, angle)); forward = Vector3.TransformNormal(forward, Matrix.CreateFromAxisAngle(axis, angle)); }
public static ulong GetPlayerSteamId(IMyCharacter character) { IMyPlayer player = MyAPIGateway.Players.GetPlayerControllingEntity(character); if (player == null) { player = MyAPIGateway.Players.GetPlayerControllingEntity(character.Parent); } return(player != null ? player.SteamUserId : ulong.MinValue); }
public static long GetPlayerIdentityId(IMyCharacter character) { IMyPlayer player = MyAPIGateway.Players.GetPlayerControllingEntity(character); if (player == null) { player = MyAPIGateway.Players.GetPlayerControllingEntity(character.Parent); } return(player != null ? player.IdentityId : 0); }
public static IMyPlayer GetPlayer(IMyCharacter character) { IMyPlayer player = MyAPIGateway.Players.GetPlayerControllingEntity(character); if (player == null) { player = MyAPIGateway.Players.GetPlayerControllingEntity(character.Parent); } return(player); }
bool IsHoldingPaintGun() { if (!OwnerIsLocalPlayer) { return(false); } IMyCharacter chr = MyAPIGateway.Session.ControlledObject as IMyCharacter; return(chr != null && chr.EquippedTool == Rifle); }
/// <summary> /// Will enable dampeners when grid is not moving or planetary gravity is detected and no ground is in range. /// </summary> private void ToggleDampenersIfNeeded(IMyCharacter character, bool isNotMoving, bool hasGravity, bool isGroundInRange, bool lastDampenerState) { if (Mod.Static.Settings.DisableAutoDampener != DisableAutoDampenerOption.Mod) { var dampenersRequired = Mod.Static.Settings.DisableAutoDampener == DisableAutoDampenerOption.All ? lastDampenerState : isNotMoving || hasGravity && !isGroundInRange; if (character.EnabledDamping != dampenersRequired) { character.SwitchDamping(); } } }
void IUpdatable.Update() { IMyCharacter chr = MyAPIGateway.Session?.ControlledObject as IMyCharacter; IMyAngleGrinder grinder = chr?.EquippedTool as IMyAngleGrinder; if (EquippedGrinder != grinder) { EquippedGrinder = grinder; GrinderChanged?.Invoke(grinder); } }
public override void Init(IMyCharacter character, Dictionary<MyStringHash, MyEntityStat> stats, string scriptName) { base.Init(character, stats, scriptName); InitPermanentEffects(); InitActions(); var health = Health; if (health != null) health.OnStatChanged += OnHealthChanged; }
public void FixShipPlayerLookAt() { IMyPlayer player = Context.Player; long playerId; if (player == null) { Context.Respond("Console has no Grids so cannot use this command. Use !fixshipmod <Gridname> instead!"); return; } else { playerId = player.IdentityId; } IMyCharacter character = player.Character; if (character == null) { Context.Respond("You have no Character currently. Make sure to spawn and be out of cockpit!"); return; } CooldownManager cooldownManager = Plugin.CommandCooldownManager; var steamId = new SteamIdCooldownKey(PlayerUtils.GetSteamId(Context.Player)); if (!cooldownManager.CheckCooldown(steamId, null, out long remainingSeconds)) { Log.Info("Cooldown for Player " + player.DisplayName + " still running! " + remainingSeconds + " seconds remaining!"); Context.Respond("Command is still on cooldown for " + remainingSeconds + " seconds."); return; } if (!CheckConformation(steamId, playerId, "nogrid", character)) { return; } try { var result = Plugin.FixShip(character, playerId); WriteResponse(result); if (result == CheckResult.SHIP_FIXED) { Log.Info("Cooldown for Player " + player.DisplayName + " started!"); cooldownManager.StartCooldown(steamId, null, Plugin.Cooldown); } } catch (Exception e) { Log.Error(e, "Error on fixing ship"); } }
/// <summary> /// Creates a NetworkNode for a character, checking radio communication. /// </summary> /// <param name="character">The character to create the NetworkNode for.</param> public RelayNode(IMyCharacter character) { IMyPlayer player = character.GetPlayer_Safe(); this.m_debugName = () => player.DisplayName; this.m_ownerId = () => player.IdentityId; this.m_entity = character as IMyEntity; this.m_player = player; this.m_comp_radio = ComponentRadio.CreateRadio(character); Registrar.Add(character as IMyEntity, this); }
protected override void StartEffect(IMyCubeBlock block) { IMyCharacter pilot = (block as MyCockpit).Pilot as IMyCharacter; if (pilot == null) { return; } Logger.DebugLog("Killing: " + pilot + ", in " + block.DisplayNameText); pilot.Kill(); }
/// <summary> /// Creates a NetworkNode for a character, checking radio communication. /// </summary> /// <param name="character">The character to create the NetworkNode for.</param> public RelayNode(IMyCharacter character) { IMyPlayer player = character.GetPlayer_Safe(); this.m_loggingName = () => player.DisplayName; this.m_logger = new Logger(GetType().Name, this.m_loggingName) { MinimumLevel = Logger.severity.INFO }; this.m_ownerId = () => player.PlayerID; this.m_entity = character as IMyEntity; this.m_player = player; this.m_comp_radio = ComponentRadio.CreateRadio(character); Registrar.Add(character as IMyEntity, this); }
private void SetCharacterReference(IMyEntity ent) { if(character == ent || !(ent is IMyCharacter)) return; if(character != null) character.OnMovementStateChanged -= CharacterMovementStateChanged; character = ent as IMyCharacter; if(character == null) return; characterDefinition = GetCharacterDefinitionFrom(ent); character.OnMovementStateChanged += CharacterMovementStateChanged; }
private void PlayerUpdate() { var playerControlled = MyAPIGateway.Session.ControlledObject; if(playerControlled != null) { if(playerControlled.Entity is IMyCharacter) { SetCharacterReference(playerControlled.Entity); } else if(playerControlled.Entity is IMyCockpit) // in a seat, certainly not gonna climb ladders { SetCharacterReference(null); } // other cases depend on having the character controlled for a bit to get the reference else if(character != null && character.Closed) { SetCharacterReference(null); } } else { character = null; } if(character != null) { var cb = MyCubeBuilder.Static; // Dynamically enable/disable UseModelIntersection on ladder blocks that you hold to have the useful effect // of being able the block when another entity is blocking the grid space but not the blocks's physical shape. // This will still have the side effect issue if you aim at a ladder block with the same ladder block. if(cb.IsActivated && cb.CubeBuilderState != null && cb.CubeBuilderState.CurrentBlockDefinition != null && LadderLogic.ladderIds.Contains(cb.CubeBuilderState.CurrentBlockDefinition.Id.SubtypeName)) { if(prevCubeBuilderDefinition == null || prevCubeBuilderDefinition.Id != cb.CubeBuilderState.CurrentBlockDefinition.Id) { if(prevCubeBuilderDefinition != null) prevCubeBuilderDefinition.UseModelIntersection = false; prevCubeBuilderDefinition = cb.CubeBuilderState.CurrentBlockDefinition; cb.CubeBuilderState.CurrentBlockDefinition.UseModelIntersection = true; } } else if(prevCubeBuilderDefinition != null) { prevCubeBuilderDefinition.UseModelIntersection = false; prevCubeBuilderDefinition = null; } var charCtrl = character as IMyControllableEntity; bool controllingCharacter = (playerControlled != null && playerControlled.Entity is IMyCharacter); IMyTerminalBlock ladder = null; MyCubeBlock ladderInternal = null; MatrixD ladderMatrix = character.WorldMatrix; // temporarily using it for character matrix, then used for ladder matrix var charPos = ladderMatrix.Translation + ladderMatrix.Up * 0.05; var charPos2 = ladderMatrix.Translation + ladderMatrix.Up * RAY_HEIGHT; var charRay = new RayD(charPos, ladderMatrix.Up); if(dismounting <= 1) // relative top dismount sequence { if(usingLadder == null) { dismounting = 2; return; } ladder = usingLadder; ladderInternal = ladder as MyCubeBlock; dismounting *= ALIGN_MUL; if(settings.clientPrediction) { ladderMatrix = ladder.WorldMatrix; var charOnLadder = ladderMatrix.Translation + ladderMatrix.Forward * (ladderInternal.BlockDefinition.ModelOffset.Z + EXTRA_OFFSET_Z); if(ladder.CubeGrid.GridSizeEnum == MyCubeSize.Large) charOnLadder += ladderMatrix.Backward; var topDir = Vector3D.Dot(character.WorldMatrix.Up, ladderMatrix.Up); var matrix = character.WorldMatrix; var halfY = ((ladderInternal.BlockDefinition.Size.Y * ladder.CubeGrid.GridSize) / 2); matrix.Translation = charOnLadder + (topDir > 0 ? ladderMatrix.Up : ladderMatrix.Down) * (halfY + 0.1f) + ladderMatrix.Backward * 0.75; character.SetWorldMatrix(MatrixD.SlerpScale(character.WorldMatrix, matrix, MathHelper.Clamp(dismounting, 0.0f, 1.0f))); character.Physics.LinearVelocity = ladder.CubeGrid.Physics.GetVelocityAtPoint(character.WorldMatrix.Translation); // sync velocity with the ladder } SetLadderStatus("Dismounting ladder...", MyFontEnum.White); if(dismounting > 1f) ExitLadder(false); return; } // UNDONE DEBUG //{ // var c = Color.Blue.ToVector4(); // MySimpleObjectDraw.DrawLine(charPos, charPos2, "WeaponLaserIgnoreDepth", ref c, 0.5f); //} // find a ladder foreach(var l in ladders.Values) { if(l.Closed || l.MarkedForClose || !l.IsFunctional) continue; if(Vector3D.DistanceSquared(l.WorldMatrix.Translation, charPos) <= UPDATE_RADIUS) { ladderInternal = l as MyCubeBlock; ladderMatrix = l.WorldMatrix; // update ladder oriented box to find character in it accurately Quaternion.CreateFromRotationMatrix(ref ladderMatrix, out ladderBox.Orientation); if(l is MyAdvancedDoor && !(l as MyAdvancedDoor).FullyOpen) { ladderBox.HalfExtent = (ladderInternal.BlockDefinition.Size * l.CubeGrid.GridSize) / 2; var offset = ladderInternal.BlockDefinition.ModelOffset; ladderBox.Center = ladderMatrix.Translation + ladderMatrix.Up * 1.125f + ladderMatrix.Forward * (offset.Z + EXTRA_OFFSET_Z); ladderBox.HalfExtent.Y = 0.25 + 0.06; // 6mm offset to avoid some inaccuracies ladderBox.HalfExtent.Z = 0.5; if(l.CubeGrid.GridSizeEnum == MyCubeSize.Large) ladderBox.Center += ladderMatrix.Backward; } else { ladderBox.HalfExtent = (ladderInternal.BlockDefinition.Size * l.CubeGrid.GridSize) / 2; ladderBox.HalfExtent.Y += 0.06; // 6mm offset to avoid some inaccuracies ladderBox.HalfExtent.Z = 0.5; var offset = ladderInternal.BlockDefinition.ModelOffset; ladderBox.Center = ladderMatrix.Translation + ladderMatrix.Forward * (offset.Z + EXTRA_OFFSET_Z); if(l.CubeGrid.GridSizeEnum == MyCubeSize.Large) ladderBox.Center += ladderMatrix.Backward; } if(!ladderBox.Contains(ref charPos) && !ladderBox.Contains(ref charPos2)) { var intersect = ladderBox.Intersects(ref charRay); if(!intersect.HasValue || intersect.Value < 0 || intersect.Value > RAY_HEIGHT) continue; } // UNDONE DEBUG //{ // { // var c = Color.Red.ToVector4(); // MySimpleObjectDraw.DrawLine(ladderBox.Center + ladderMatrix.Down * ladderBox.HalfExtent.Y, ladderBox.Center + ladderMatrix.Up * ladderBox.HalfExtent.Y, "WeaponLaserIgnoreDepth", ref c, 0.01f); // } // // if(debugBox == null) // { // debugBox = new MyEntity(); // debugBox.Init(null, @"Models\Debug\Error.mwm", null, null, null); // debugBox.PositionComp.LocalMatrix = Matrix.Identity; // debugBox.Flags = EntityFlags.Visible | EntityFlags.NeedsDraw | EntityFlags.NeedsDrawFromParent | EntityFlags.InvalidateOnMove; // debugBox.OnAddedToScene(null); // debugBox.Render.Transparency = 0.5f; // debugBox.Render.RemoveRenderObjects(); // debugBox.Render.AddRenderObjects(); // } // var matrix = MatrixD.CreateWorld(ladderBox.Center, ladderMatrix.Forward, ladderMatrix.Up); // var scale = ladderBox.HalfExtent * 2; // MatrixD.Rescale(ref matrix, ref scale); // debugBox.PositionComp.SetWorldMatrix(matrix); //} ladder = l; ladderInternal = l as MyCubeBlock; break; } } if(ladder != null) { var offset = ladderInternal.BlockDefinition.ModelOffset; var charOnLadder = ladderMatrix.Translation + ladderMatrix.Forward * (offset.Z + EXTRA_OFFSET_Z); if(ladder.CubeGrid.GridSizeEnum == MyCubeSize.Large) charOnLadder += ladderMatrix.Backward; if(++skipRetryGravity >= GRAVITY_UPDATERATE) { skipRetryGravity = 0; alignedToGravity = true; var gravity = MyParticlesManager.CalculateGravityInPoint(character.WorldMatrix.Translation); var gravityLength = gravity.Normalize(); if(gravityLength > 0) { float gravDot = Vector3.Dot(gravity, ladderMatrix.Down); if(!(gravDot >= 0.9f || gravDot <= -0.9f)) { alignedToGravity = false; } } } //bool readInput = InputHandler.IsInputReadable(); // HACK use before GetPressedOr() once ActiveGameplayScreen's NRE is resolved if(!alignedToGravity) { bool pressed = InputHandler.GetPressedOr(settings.useLadder1, settings.useLadder2, false, false) && InputHandler.IsInputReadable(); // needs to support hold-press, so don't set JustPressed to true! if(pressed) SetLadderStatus("Gravity not parallel to ladder!", MyFontEnum.Red, 1000); if(usingLadder != null) ExitLadder(false); return; } if(usingLadder == null) // first ladder interaction { //var controlUse = MyAPIGateway.Input.GetGameControl(MyControlsSpace.USE); // //if(!controlUse.IsPressed()) //{ // string assigned = (controlUse.GetKeyboardControl() != MyKeys.None ? MyAPIGateway.Input.GetKeyName(controlUse.GetKeyboardControl()) : (controlUse.GetMouseControl() != MyMouseButtonsEnum.None ? MyAPIGateway.Input.GetName(controlUse.GetMouseControl()) : "(NONE)")) + (controlUse.GetSecondKeyboardControl() != MyKeys.None ? " or " + MyAPIGateway.Input.GetKeyName(controlUse.GetSecondKeyboardControl()) : null); // SetLadderStatus("Press "+assigned+" to use the ladder.", MyFontEnum.White); // return; //} if(grabOnLoad) { grabOnLoad = false; } else { aimingAtLadder = true; if(settings.useLadder1 == null && settings.useLadder2 == null) { SetLadderStatus("Ladder interaction is unassigned, edit the settings.cfg file!\nFor now you can use the USE key.", MyFontEnum.Red); if(!MyAPIGateway.Input.IsGameControlPressed(MyControlsSpace.USE)) return; } else { bool pressed = InputHandler.GetPressedOr(settings.useLadder1, settings.useLadder2, false, false) && InputHandler.IsInputReadable(); // needs to support hold-press, so don't set JustPressed to true! if(!pressed) { #if !STABLE // STABLE CONDITION if(!highlightedLadders.Contains(ladder.EntityId)) { if(highlightedLadders.Count > 0) { foreach(var id in highlightedLadders) { MyVisualScriptLogicProvider.SetHighlight(LADDER_NAME_PREFIX + id, false); } highlightedLadders.Clear(); } var envDef = MyDefinitionManager.Static.EnvironmentDefinition; var color = envDef.ContourHighlightColor; var thick = (int)envDef.ContourHighlightThickness; highlightedLadders.Add(ladder.EntityId); MyVisualScriptLogicProvider.SetHighlight(ladder.Name, true, thick, LADDER_HIGHLIGHT_PULSE, color); var ladderGrid = ladder.CubeGrid; for(int i = 1; i <= 10; i++) { var slim = ladderGrid.GetCubeBlock(ladderGrid.WorldToGridInteger(ladderMatrix.Translation + ladderMatrix.Up * i * ladderGrid.GridSize)); if(slim?.FatBlock?.GameLogic?.GetAs<LadderLogic>() == null) break; var id = slim.FatBlock.EntityId; highlightedLadders.Add(id); MyVisualScriptLogicProvider.SetHighlight(LADDER_NAME_PREFIX + id, true, thick, LADDER_HIGHLIGHT_PULSE, color); } for(int i = 1; i <= 10; i++) { var slim = ladderGrid.GetCubeBlock(ladderGrid.WorldToGridInteger(ladderMatrix.Translation + ladderMatrix.Down * i * ladderGrid.GridSize)); if(slim?.FatBlock?.GameLogic?.GetAs<LadderLogic>() == null) break; var id = slim.FatBlock.EntityId; highlightedLadders.Add(id); MyVisualScriptLogicProvider.SetHighlight(LADDER_NAME_PREFIX + id, true, thick, LADDER_HIGHLIGHT_PULSE, color); } } #endif SetLadderStatus("Press " + InputHandler.GetFriendlyStringOr(settings.useLadder1, settings.useLadder2) + " to use the ladder.", MyFontEnum.White); return; } } } skipRefreshAnim = 60; mounting = (controllingCharacter ? ALIGN_STEP : 2); usingLadder = ladder; SendLadderData(LadderAction.MOUNT, entId: ladder.EntityId); LadderAnim(character, LadderAnimation.MOUNTING); } if(usingLadder != ladder) { usingLadder = ladder; SendLadderData(LadderAction.CHANGE_LADDER, entId: ladder.EntityId); } if(charCtrl.Entity.Physics == null) { ExitLadder(false); return; } if(settings.clientPrediction) character.Physics.LinearVelocity = ladder.CubeGrid.Physics.GetVelocityAtPoint(character.WorldMatrix.Translation); // sync velocity with the ladder if(skipRefreshAnim > 0 && --skipRefreshAnim == 0) // force refresh animation after mounting due to an issue { var anim = lastLadderAnim; lastLadderAnim = LadderAnimation.NONE; LadderAnim(character, anim); } if(mounting <= 1) // mounting on ladder sequence { mounting *= ALIGN_MUL; if(settings.clientPrediction) { float align = Vector3.Dot(ladderMatrix.Up, character.WorldMatrix.Up); var matrix = MatrixD.CreateFromDir(ladderMatrix.Backward, (align > 0 ? ladderMatrix.Up : ladderMatrix.Down)); var halfY = ((ladderInternal.BlockDefinition.Size.Y * ladder.CubeGrid.GridSize) / 2); var diff = Vector3D.Dot(character.WorldMatrix.Translation, ladderMatrix.Up) - Vector3D.Dot(charOnLadder, ladderMatrix.Up); matrix.Translation = charOnLadder + ladderMatrix.Up * MathHelper.Clamp(diff, -halfY, halfY); character.SetWorldMatrix(MatrixD.SlerpScale(character.WorldMatrix, matrix, MathHelper.Clamp(mounting, 0.0f, 1.0f))); } if(mounting >= 0.75f && charCtrl.EnabledThrusts) // delayed turning off thrusts because gravity aligns you faster and can make you fail to attach to the ladder charCtrl.SwitchThrusts(); SetLadderStatus("Mounting ladder...", MyFontEnum.White); return; } // TODO jetpack assited climb/descend ? / gravity assisted descend ? if(charCtrl.EnabledThrusts) { if(!learned[4]) learned[4] = true; ExitLadder(false); // leave ladder if jetpack is turned on return; } // HACK use once input reading NRE is fixed //if(!controllingCharacter) // disable ladder control if not controlling character // readInput = false; bool movingSideways = false; var analogInput = MyAPIGateway.Input.GetPositionDelta(); // HACK use in-line once NRE is fixed if(!controllingCharacter) analogInput = Vector3.Zero; else if(analogInput.LengthSquared() > 0 && !InputHandler.IsInputReadable()) analogInput = Vector3.Zero; if(analogInput.Y < 0) // crouch { if(!learned[4]) learned[4] = true; ExitLadder(false); return; } float move = MathHelper.Clamp((float)Math.Round(-analogInput.Z, 1), -1, 1); // forward/backward float side = MathHelper.Clamp((float)Math.Round(analogInput.X, 1), -1, 1); // left/right //float move = readInput ? MathHelper.Clamp(MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.FORWARD) - MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.BACKWARD), -1, 1) : 0; //float side = readInput ? MathHelper.Clamp(MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.STRAFE_RIGHT) - MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.STRAFE_LEFT), -1, 1) : 0; var alignVertical = ladderMatrix.Up.Dot(character.WorldMatrix.Up); if(!loadedAllLearned) { bool allLearned = (learned[0] && learned[1] && learned[2] && learned[3] && learned[4]); for(int i = 0; i < learned.Length; i++) { if(learnNotify[i] == null) learnNotify[i] = MyAPIGateway.Utilities.CreateNotification(""); learnNotify[i].Text = (learned[i] ? LEARN_CHECK : LEARN_UNCHECK) + learnText[i]; learnNotify[i].Font = (learned[i] ? MyFontEnum.White : MyFontEnum.DarkBlue); learnNotify[i].AliveTime = (allLearned ? 1000 : 100); learnNotify[i].Show(); } if(allLearned) { SaveLearn(); loadedAllLearned = true; } } var view = MyAPIGateway.Session.ControlledObject.GetHeadMatrix(false, true); float lookVertical = Vector3.Dot(character.WorldMatrix.Up, view.Forward); if(settings.relativeControls) // climbing relative to camera { float verticalModifier = MathHelper.Clamp((lookVertical + 0.65f) / 0.5f, -0.5f, 1.0f); if(verticalModifier < 0) verticalModifier *= 2; move = (float)Math.Round(move * verticalModifier, 1); } if(analogInput.Y > 0) // jump { if(characterMovementState == MyCharacterMovementEnum.Jump) // this is still fine for avoiding jump as the character still is able to jump without needing feet on the ground { ExitLadder(false); // only release if on the floor as the character will jump regardless return; } if(settings.clientPrediction) character.Physics.LinearVelocity += view.Forward * (characterDefinition == null ? VEL_JUMP : 200 * characterDefinition.JumpForce) * TICKRATE; SendLadderData(LadderAction.JUMP_OFF, vec: view.Forward); LadderAnim(character, LadderAnimation.JUMP_OFF); if(!learned[3]) learned[3] = true; ExitLadder(false); return; } bool sprint = (characterDefinition != null && characterDefinition.Jetpack != null && MyAPIGateway.Input.IsGameControlPressed(MyControlsSpace.SPRINT)); if(Math.Abs(side) > 0.0001f) { if(settings.relativeControls) // side dismounting relative to camera { var alignForward = ladderMatrix.Backward.Dot(character.WorldMatrix.Forward); if(alignForward < 0) side = -side; } float speed = (characterDefinition == null ? (sprint ? VEL_SIDE : VEL_CLIMB) : CHAR_SPEED_MUL * (sprint ? characterDefinition.MaxSprintSpeed : characterDefinition.MaxRunStrafingSpeed)); if(settings.clientPrediction) character.Physics.LinearVelocity += side * (alignVertical > 0 ? ladderMatrix.Left : ladderMatrix.Right) * speed * TICKRATE; LadderAnim(character, (side > 0 ? LadderAnimation.DISMOUNT_LEFT : LadderAnimation.DISMOUNT_RIGHT)); movingSideways = true; if(!learned[2]) learned[2] = true; } else { // aligning player to ladder if(settings.clientPrediction) { Vector3 dir = charOnLadder - charPos; Vector3 vel = dir - (ladderMatrix.Up * Vector3D.Dot(dir, ladderMatrix.Up)); // projecting up/down direction to ignore it float len = vel.Normalize(); if(len >= ALIGN_ACCURACY) { float speed = (characterDefinition == null ? (sprint ? VEL_SIDE : VEL_CLIMB) : CHAR_SPEED_MUL * (sprint ? characterDefinition.MaxRunStrafingSpeed : characterDefinition.MaxWalkStrafingSpeed)); len = MathHelper.Clamp(len, 0.1f, 1); character.Physics.LinearVelocity += vel * len * speed * TICKRATE; } } } // TODO find a way to control view { //var ctrl2 = (Sandbox.Game.Entities.IMyControllableEntity)character; // //ctrl2.HeadLocalYAngle = 0; //ctrl2.HeadLocalXAngle = 0; // // or MoveAndRotate() ? // or... angularvelocity ? // or I dunno! } if(Math.Abs(move) > 0.0001f) { if(!learned[0]) learned[0] = true; var halfY = ((ladderInternal.BlockDefinition.Size.Y * ladder.CubeGrid.GridSize) / 2); var edge = charOnLadder + ((alignVertical > 0 ? ladderMatrix.Up : ladderMatrix.Down) * halfY); // climb over at the end when climbing up if(move > 0 && Vector3D.DistanceSquared(charPos, edge) <= 0.0625) // 0.25 squared { var nextBlockWorldPos = ladderMatrix.Translation + ladderMatrix.Forward * offset.Z + ((alignVertical > 0 ? ladderMatrix.Up : ladderMatrix.Down) * (halfY + 0.1f)); var nextBlockPos = ladder.CubeGrid.WorldToGridInteger(nextBlockWorldPos); var slim = ladder.CubeGrid.GetCubeBlock(nextBlockPos); // if the next block is not a ladder, dismount if(slim == null || !(slim.FatBlock is IMyTerminalBlock) || !LadderLogic.ladderIds.Contains(slim.FatBlock.BlockDefinition.SubtypeId)) { dismounting = ALIGN_STEP; SendLadderData(LadderAction.DISMOUNT); return; } } // on the floor and moving backwards makes you dismount if(move < 0) { var feetStart = character.WorldMatrix.Translation + character.WorldMatrix.Up * 0.2; // a bit higher because the floor might clip through the character var feetTarget = feetStart + character.WorldMatrix.Down * 0.3; IHitInfo hit; if(MyAPIGateway.Physics.CastRay(feetStart, feetTarget, out hit, COLLISSIONLAYER_NOCHARACTER)) { // need to check the block under the ladder if it's anything but a ladder because "standing" stance occurs when character rests on its chest-sphere collision mesh too var prevBlockWorldPos = ladderMatrix.Translation + ladderMatrix.Forward * offset.Z + (alignVertical > 0 ? ladderMatrix.Down : ladderMatrix.Up) * (halfY + 0.1f); var prevBlockPos = ladder.CubeGrid.WorldToGridInteger(prevBlockWorldPos); var slim = ladder.CubeGrid.GetCubeBlock(prevBlockPos); // if it's not a ladder, check the distance and confirm your feet are close to its edge if(slim == null || !(slim.FatBlock is IMyTerminalBlock) || !LadderLogic.ladderIds.Contains(slim.FatBlock.BlockDefinition.SubtypeId)) { // get the block's edge and the character feet position only along the ladder's up/down axis var blockPosProjectedUp = ladderMatrix.Up * Vector3D.Dot(prevBlockWorldPos, ladderMatrix.Up); var charPosProjectedUp = ladderMatrix.Up * Vector3D.Dot(character.WorldMatrix.Translation, ladderMatrix.Up); if(Vector3D.DistanceSquared(blockPosProjectedUp, charPosProjectedUp) <= 0.04) // 0.2 squared { ExitLadder(false); // to recap: if you're moving char-relative down and in "standing" stance and the block below is not a ladder and you're closer than 0.1m to its edge, then let go of the ladder. return; } } } } // climbing on the ladder if(!learned[1] && sprint) learned[1] = true; float speed = (characterDefinition == null ? (sprint ? VEL_SPRINT : VEL_CLIMB) : CHAR_SPEED_MUL * (sprint ? characterDefinition.MaxSprintSpeed : characterDefinition.MaxRunSpeed)); if(settings.clientPrediction) character.Physics.LinearVelocity += (alignVertical > 0 ? ladderMatrix.Up : ladderMatrix.Down) * move * speed * TICKRATE; if(!movingSideways) LadderAnim(character, (move > 0 ? LadderAnimation.UP : LadderAnimation.DOWN)); } else if(!movingSideways) { LadderAnim(character, LadderAnimation.IDLE); } SendLadderData(LadderAction.CLIMB, climb: (alignVertical > 0 ? move : -move), side: (alignVertical > 0 ? side : -side), sprint: sprint); return; } } ExitLadder(); }
public Character(VRage.ByteStream stream) : base(stream) { CharacterEntity = Entity as IMyCharacter; }
public CharacterStateTracker(IMyCharacter character) { Registrar.Add((IMyEntity)character, this); character.OnMovementStateChanged += character_OnMovementStateChanged; }
public virtual void Init(IMyCharacter character, Dictionary<MyStringHash, MyEntityStat> stats) { m_character = character; m_stats = stats; }
public override void Init(IMyCharacter character, Dictionary<MyStringHash, MyEntityStat> stats) { base.Init(character, stats); InitPermanentEffects(); }
public CR_Character(IMyCharacter character) { this.m_character = character; this.m_identity = character.GetIdentity_Safe(); }
protected virtual void OnCharacterChanged(IMyCharacter oldCharacter) {}
/// <summary> /// Creates a radio component for a character. /// </summary> public static ComponentRadio CreateRadio(IMyCharacter character) { return new CR_Character(character); }