diff --git a/GamecraftModdingAPI/GamecraftModdingAPI.csproj b/GamecraftModdingAPI/GamecraftModdingAPI.csproj index 074c5b6..c72b77a 100644 --- a/GamecraftModdingAPI/GamecraftModdingAPI.csproj +++ b/GamecraftModdingAPI/GamecraftModdingAPI.csproj @@ -3,7 +3,7 @@ net472 true - 1.1.0 + 1.2.0 Exmods GNU General Public Licence 3+ https://git.exmods.org/modtainers/GamecraftModdingAPI diff --git a/GamecraftModdingAPI/Player.cs b/GamecraftModdingAPI/Player.cs index 0b7a134..501c3df 100644 --- a/GamecraftModdingAPI/Player.cs +++ b/GamecraftModdingAPI/Player.cs @@ -4,6 +4,7 @@ using Unity.Mathematics; using RobocraftX.Common; using GamecraftModdingAPI.Players; +using GamecraftModdingAPI.Blocks; namespace GamecraftModdingAPI { @@ -199,6 +200,125 @@ namespace GamecraftModdingAPI } } + /// + /// The player's initial health when entering Simulation (aka Time Running) mode. + /// + /// The initial health. + public float InitialHealth + { + get => playerEngine.GetInitialHealth(Id); + + set + { + playerEngine.SetInitialHealth(Id, value); + } + } + + /// + /// The player's current health in Simulation (aka Time Running) mode. + /// + /// The current health. + public float CurrentHealth + { + get => playerEngine.GetCurrentHealth(Id); + + set + { + playerEngine.DamagePlayer(Id, CurrentHealth - value); + } + } + + /// + /// Whether this is damageable. + /// + /// true if damageable; otherwise, false. + public bool Damageable + { + get => playerEngine.GetDamageable(Id); + + set + { + playerEngine.SetDamageable(Id, value); + } + } + + /// + /// The player's lives when initially entering Simulation (aka Time Running) mode. + /// + /// The initial lives. + public uint InitialLives + { + get => playerEngine.GetInitialLives(Id); + + set => playerEngine.SetInitialLives(Id, value); + } + + /// + /// The player's current lives in Simulation (aka Time Running) mode. + /// + /// The current lives. + public uint CurrentLives + { + get => playerEngine.GetCurrentLives(Id); + + set => playerEngine.SetCurrentLives(Id, value); + } + + /// + /// Whether the Game Over screen is displayed for the player. + /// + /// true if game over; otherwise, false. + public bool GameOver + { + get => playerEngine.GetGameOverScreen(Id); + } + + /// + /// Whether the player is dead. + /// If true, hopefully it was quick. + /// + /// true if dead; otherwise, false. + public bool Dead + { + get => playerEngine.IsDead(Id); + } + + /// + /// The player's selected block ID in their hand. + /// + /// The selected block. + public BlockIDs SelectedBlock + { + get + { + return (BlockIDs)playerEngine.GetSelectedBlock(Id); + } + } + + /// + /// The player's selected block color in their hand. + /// + /// The selected block's color. + public BlockColors SelectedColor + { + get + { + return (BlockColors)playerEngine.GetSelectedColor(Id); + } + } + + /// + /// The player's selected block colour in their hand. + /// + /// The selected block's colour. + public BlockColors SelectedColour + { + get + { + return (BlockColors)playerEngine.GetSelectedColor(Id); + } + } + // object methods /// diff --git a/GamecraftModdingAPI/Players/PlayerEngine.cs b/GamecraftModdingAPI/Players/PlayerEngine.cs index 1fa1296..c86a4ae 100644 --- a/GamecraftModdingAPI/Players/PlayerEngine.cs +++ b/GamecraftModdingAPI/Players/PlayerEngine.cs @@ -6,18 +6,20 @@ using RobocraftX.Character.Movement; using RobocraftX.Common.Players; using RobocraftX.Common.Input; using RobocraftX.Physics; +using RobocraftX.Blocks.Ghost; +using RobocraftX.Character.Camera; +using RobocraftX.Character.Factories; +using Gamecraft.CharacterVulnerability; +using Gamecraft.CharacterVulnerability.Entities; using Svelto.ECS; using Unity.Mathematics; using Unity.Physics; using GamecraftModdingAPI.Engines; -using RobocraftX.Blocks.Ghost; -using RobocraftX.Character.Camera; -using RobocraftX.Character.Factories; namespace GamecraftModdingAPI.Players { - internal class PlayerEngine : IApiEngine + internal class PlayerEngine : IApiEngine, IFactoryEngine { public string Name { get; } = "GamecraftModdingAPIPlayerGameEngine"; @@ -25,6 +27,8 @@ namespace GamecraftModdingAPI.Players public bool isRemovable => false; + public IEntityFactory Factory { set; private get; } + private bool isReady = false; public void Dispose() @@ -188,7 +192,7 @@ namespace GamecraftModdingAPI.Players public float? GetLastPingTime(uint playerId, PlayerType type) { - EGID egid = new EGID(playerId, GroupFromEnum(type)); + EGID egid = new EGID(playerId, PlayerGroupFromEnum(type)); if (entitiesDB.Exists(egid)) { return entitiesDB.QueryEntity(egid).lastPingTimeSinceLevelLoad; @@ -196,10 +200,150 @@ namespace GamecraftModdingAPI.Players return null; } + public float GetInitialHealth(uint playerId) + { + if (GetCharacterStruct(playerId, out CharacterHealthEntityStruct c)) + { + return c.initialHealth; + } + return -1f; + } + + public bool SetInitialHealth(uint playerId, float val) + { + if (GetCharacterStruct(playerId, out CharacterHealthEntityStruct c)) + { + c.initialHealth = val; + return true; + } + return false; + } + + public float GetCurrentHealth(uint playerId) + { + if (GetCharacterStruct(playerId, out CharacterHealthEntityStruct c)) + { + return c.currentHealth; + } + return -1f; + } + + public bool SetCurrentHealth(uint playerId, float val) + { + if (GetCharacterStruct(playerId, out CharacterHealthEntityStruct c)) + { + c.currentHealth = val; + return true; + } + return false; + } + + public bool DamagePlayer(uint playerId, float amount) + { + Factory.BuildEntity( + new EGID(CharacterVulnerabilityExclusiveGroups.NextDamageEntityId, CharacterVulnerabilityExclusiveGroups.CharacterDamageExclusiveGroup) + ).Init(new DamageEntityStruct + { + damage = amount, + targetPlayerEntityId = playerId, + }); + return true; + } + + public bool GetDamageable(uint playerId) + { + if (GetCharacterStruct(playerId, out CharacterHealthEntityStruct c)) + { + return c.canTakeDamageStat; + } + return false; + } + + public bool SetDamageable(uint playerId, bool val) + { + if (GetCharacterStruct(playerId, out CharacterHealthEntityStruct ches)) + { + ches.canTakeDamage = val; + ches.canTakeDamage = val; + return true; + } + return false; + } + + public uint GetInitialLives(uint playerId) + { + if (GetCharacterStruct(playerId, out CharacterLivesEntityComponent c)) + { + return c.initialLives; + } + return uint.MaxValue; + } + + public bool SetInitialLives(uint playerId, uint val) + { + if (GetCharacterStruct(playerId, out CharacterLivesEntityComponent c)) + { + c.initialLives = val; + return true; + } + return false; + } + + public uint GetCurrentLives(uint playerId) + { + if (GetCharacterStruct(playerId, out CharacterLivesEntityComponent c)) + { + return c.currentLives; + } + return uint.MaxValue; + } + + public bool SetCurrentLives(uint playerId, uint val) + { + if (GetCharacterStruct(playerId, out CharacterLivesEntityComponent c)) + { + c.currentLives = val; + return true; + } + return false; + } + + public bool GetGameOverScreen(uint playerId) + { + if (GetCharacterStruct(playerId, out CharacterLivesEntityComponent c)) + { + return c.gameOverScreen; + } + return false; + } + + public bool IsDead(uint playerId) + { + return entitiesDB.Exists(playerId, CharacterExclusiveGroups.DeadGroup); + } + + public int GetSelectedBlock(uint playerId) + { + if (GetCharacterStruct(playerId, out EquippedPartStruct c)) + { + return c.SelectedDBPartID; + } + return ushort.MaxValue; + } + + public byte GetSelectedColor(uint playerId) + { + if (GetCharacterStruct(playerId, out EquippedColourStruct c)) + { + return c.indexInPalette; + } + return 255; + } + // reusable methods [MethodImpl(MethodImplOptions.AggressiveInlining)] - private ExclusiveGroup GroupFromEnum(PlayerType type) + private ExclusiveGroup PlayerGroupFromEnum(PlayerType type) { return type == PlayerType.Local ? PlayersExclusiveGroups.LocalPlayers : PlayersExclusiveGroups.RemotePlayers; } diff --git a/doxygen.conf b/doxygen.conf index bdd0ed0..19df3c4 100644 --- a/doxygen.conf +++ b/doxygen.conf @@ -38,7 +38,7 @@ PROJECT_NAME = "GamecraftModdingAPI" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "v1.1.0" +PROJECT_NUMBER = "v1.2.0" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a