/// <summary> /// Spawns the player if there isn't currently a player node existing /// </summary> public void SpawnPlayer() { if (Player != null) { return; } Player = SpawnHelpers.SpawnMicrobe(GameWorld.PlayerSpecies, new Vector3(0, 0, 0), rootOfDynamicallySpawned, SpawnHelpers.LoadMicrobeScene(), false, Clouds, CurrentGame); Player.AddToGroup("player"); Player.OnDeath = OnPlayerDied; Player.OnReproductionStatus = OnPlayerReproductionStatusChanged; Camera.ObjectToFollow = Player; if (spawnedPlayer) { // Random location on respawn var random = new Random(); Player.Translation = new Vector3( random.Next(Constants.MIN_SPAWN_DISTANCE, Constants.MAX_SPAWN_DISTANCE), 0, random.Next(Constants.MIN_SPAWN_DISTANCE, Constants.MAX_SPAWN_DISTANCE)); } TutorialState.SendEvent(TutorialEventType.MicrobePlayerSpawned, new MicrobeEventArgs(Player), this); spawnedPlayer = true; playerRespawnTimer = Constants.PLAYER_RESPAWN_TIME; }
public MicrobeSpawner(Species species, CompoundCloudSystem cloudSystem, GameProperties currentGame) { this.species = species ?? throw new ArgumentException("species is null"); microbeScene = SpawnHelpers.LoadMicrobeScene(); this.cloudSystem = cloudSystem; this.currentGame = currentGame; random = new Random(); }
/// <summary> /// Spawns the player if there isn't currently a player node existing /// </summary> public void SpawnPlayer() { if (Player != null) { return; } Player = SpawnHelpers.SpawnMicrobe(GameWorld.PlayerSpecies, new Vector3(0, 0, 0), rootOfDynamicallySpawned, SpawnHelpers.LoadMicrobeScene(), false, Clouds, CurrentGame); Player.AddToGroup("player"); Player.OnDeath = (microbe) => { GD.Print("The player has died"); Player = null; Camera.ObjectToFollow = null; }; Player.OnReproductionStatus = (microbe, ready) => { if (ready) { HUD.ShowReproductionDialog(); } else { HUD.HideReproductionDialog(); } }; Camera.ObjectToFollow = Player; if (spawnedPlayer) { // Random location on respawn var random = new Random(); Player.Translation = new Vector3( random.Next(Constants.MIN_SPAWN_DISTANCE, Constants.MAX_SPAWN_DISTANCE), 0, random.Next(Constants.MIN_SPAWN_DISTANCE, Constants.MAX_SPAWN_DISTANCE)); } spawnedPlayer = true; playerRespawnTimer = Constants.PLAYER_RESPAWN_TIME; }
/// <summary> /// Triggers reproduction on this cell (even if not ready) /// Ignores security checks. If you want those checks, use <see cref="Divide"/> /// </summary> public void ForceDivide() { // Separate the two cells. var separation = new Vector3(Radius, 0, 0); // Create the one daughter cell. var copyEntity = SpawnHelpers.SpawnMicrobe(Species, Translation + separation, GetParent(), SpawnHelpers.LoadMicrobeScene(), true, cloudSystem, CurrentGame); // Make it despawn like normal SpawnSystem.AddEntityToTrack(copyEntity); // Remove the compounds from the created cell copyEntity.Compounds.ClearCompounds(); var keys = new List <Compound>(Compounds.Compounds.Keys); var reproductionCompounds = copyEntity.CalculateTotalCompounds(); // Split the compounds between the two cells. foreach (var compound in keys) { var amount = Compounds.GetCompoundAmount(compound); if (amount <= 0) { continue; } // If the compound is for reproduction we give player and NPC microbes different amounts. if (reproductionCompounds.TryGetValue(compound, out float divideAmount)) { // The amount taken away from the parent cell depends on if it is a player or NPC. Player // cells always have 50% of the compounds they divided with taken away. float amountToTake = amount * 0.5f; if (!IsPlayerMicrobe) { // NPC parent cells have at least 50% taken away, or more if it would leave them // with more than 90% of the compound it would take to immediately divide again. amountToTake = Math.Max(amountToTake, amount - (divideAmount * 0.9f)); } Compounds.TakeCompound(compound, amountToTake); // Since the child cell is always an NPC they are given either 50% of the compound from the // parent, or 90% of the amount required to immediately divide again, whichever is smaller. float amountToGive = Math.Min(amount * 0.5f, divideAmount * 0.9f); var addedCompound = copyEntity.Compounds.AddCompound(compound, amountToGive); if (addedCompound < amountToGive) { // TODO: handle the excess compound that didn't fit in the other cell } } else { // Non-reproductive compounds just always get split evenly to both cells. Compounds.TakeCompound(compound, amount * 0.5f); var amountAdded = copyEntity.Compounds.AddCompound(compound, amount * 0.5f); if (amountAdded < amount) { // TODO: handle the excess compound that didn't fit in the other cell } } } // Play the split sound PlaySoundEffect("res://assets/sounds/soundeffects/reproduction.ogg"); }
private void RespawnEntitiesFromSave(MicrobeStage savedMicrobeStage) { if (savedMicrobeStage.Player != null && !savedMicrobeStage.Player.Dead) { SpawnPlayer(); Player.ApplyPropertiesFromSave(savedMicrobeStage.Player); } if (savedGameEntities == null) { GD.PrintErr("Saved microbe stage contains no entities to load"); return; } var microbeScene = SpawnHelpers.LoadMicrobeScene(); var chunkScene = SpawnHelpers.LoadChunkScene(); var agentScene = SpawnHelpers.LoadAgentScene(); // This only should be used for things that get overridden anyway from the saved properties var random = new Random(); foreach (var thing in savedGameEntities) { // Skip the player as it was already loaded if (thing == savedMicrobeStage.Player) { continue; } switch (thing) { case Microbe casted: { var spawned = SpawnHelpers.SpawnMicrobe(casted.Species, Vector3.Zero, rootOfDynamicallySpawned, microbeScene, !casted.IsPlayerMicrobe, Clouds, CurrentGame); spawned.ApplyPropertiesFromSave(casted); break; } case FloatingChunk casted: { var spawned = SpawnHelpers.SpawnChunk(casted.CreateChunkConfigurationFromThis(), casted.Translation, rootOfDynamicallySpawned, chunkScene, Clouds, random); spawned.ApplyPropertiesFromSave(casted); break; } case AgentProjectile casted: { var spawned = SpawnHelpers.SpawnAgent(casted.Properties, casted.Amount, casted.TimeToLiveRemaining, casted.Translation, Vector3.Forward, rootOfDynamicallySpawned, agentScene, null); spawned.ApplyPropertiesFromSave(casted); // TODO: mapping from old microbe to recreated microbe to set emitter here break; } default: GD.PrintErr("Unknown entity type to load from save: ", thing.GetType()); break; } } // Clear this to make saving again work savedGameEntities = null; }