public virtual void DetectPlayer() { //detect players positioned on the portal bit of the gateway var playersFound = Matrix.Get <ObjectBehaviour>(registerTile.LocalPositionServer + Vector3Int.up, ObjectType.Player, true); if (!SpawnedMobs && selectedWorld != null && playersFound.Count() > 0) { selectedWorld.SetUp(this); Logger.Log("Gateway Spawned Mobs"); if (selectedWorld.GetComponent <MobSpawnControlScript>() != null) { selectedWorld.GetComponent <MobSpawnControlScript>().SpawnMobs(); } SpawnedMobs = true; } foreach (ObjectBehaviour player in playersFound) { var coord = new Vector2(Position.x, Position.y); Chat.AddLocalMsgToChat(Message, coord, gameObject); SoundManager.PlayNetworkedForPlayer(player.gameObject, "StealthOff"); //very weird, sometimes does the sound other times not. TransportPlayers(player); } foreach (var objects in Matrix.Get <ObjectBehaviour>(registerTile.LocalPositionServer + Vector3Int.up, ObjectType.Object, true)) { TransportObjectsItems(objects); } foreach (var items in Matrix.Get <ObjectBehaviour>(registerTile.LocalPositionServer + Vector3Int.up, ObjectType.Item, true)) { TransportObjectsItems(items); } }
protected override void OnDeathActions() { if (CustomNetworkManager.Instance._isServer) { ConnectedPlayer player = PlayerList.Instance.Get(gameObject); string killerName = null; if (LastDamagedBy != null) { killerName = PlayerList.Instance.Get(LastDamagedBy)?.Name; } if (killerName == null) { killerName = "Stressful work"; } string playerName = player?.Name ?? "dummy"; if (killerName == playerName) { Chat.AddActionMsgToChat(gameObject, "You committed suicide, what a waste.", $"{playerName} committed suicide."); } else if (killerName.EndsWith(playerName)) { // chain reactions Chat.AddActionMsgToChat(gameObject, $" You screwed yourself up with some help from {killerName}", $"{playerName} screwed himself up with some help from {killerName}"); } else { PlayerList.Instance.TrackKill(LastDamagedBy, gameObject); } //drop items in hand if (itemStorage != null) { Inventory.ServerDrop(itemStorage.GetNamedItemSlot(NamedSlot.leftHand)); Inventory.ServerDrop(itemStorage.GetNamedItemSlot(NamedSlot.rightHand)); } if (isServer) { EffectsFactory.BloodSplat(transform.position, BloodSplatSize.large, bloodColor); string descriptor = null; if (player != null) { descriptor = player?.Script?.characterSettings?.PossessivePronoun(); } if (descriptor == null) { descriptor = "their"; } Chat.AddLocalMsgToChat($"<b>{playerName}</b> seizes up and falls limp, {descriptor} eyes dead and lifeless...", (Vector3)registerPlayer.WorldPositionServer); } PlayerDeathMessage.Send(gameObject); } }
private static IEnumerator SpamChatCoroutine() { if (isSpamming == false) { yield break; } var fakePlayer = ConnectedPlayer.Invalid; fakePlayer.Username = "******"; yield return(WaitFor.Seconds(Random.Range(0.00001f, 0.01f))); switch (Random.Range(1, 4)) { case 1: Chat.AddExamineMsgToClient($"Examination: {DateTime.Now.ToFileTimeUtc()}"); break; case 2: Chat.AddChatMsgToChat(fakePlayer, DateTime.Now.ToFileTimeUtc().ToString(), ChatChannel.OOC, Loudness.NORMAL); break; default: Chat.AddLocalMsgToChat($"Local Message: {DateTime.Now.ToFileTimeUtc()}", new Vector2(Random.value * 100, Random.value * 100), null); break; } Chat.Instance.StartCoroutine(SpamChatCoroutine()); }
public virtual void DetectPlayer() { // detect players positioned on the portal bit of the gateway var playersFound = Matrix.Get <ObjectBehaviour>(registerTile.LocalPositionServer + Vector3Int.up, ObjectType.Player, true); if (SpawnedMobs == false && selectedWorld != null && playersFound.Count() > 0) { selectedWorld.SetUp(this); Logger.Log("Gateway Spawned Mobs", Category.Machines); if (selectedWorld.GetComponent <MobSpawnControlScript>() != null) { selectedWorld.GetComponent <MobSpawnControlScript>().SpawnMobs(); } SpawnedMobs = true; } foreach (ObjectBehaviour player in playersFound) { var coord = new Vector2(Position.x, Position.y); Chat.AddLocalMsgToChat(Message, coord, gameObject); _ = SoundManager.PlayNetworkedForPlayer(player.gameObject, CommonSounds.Instance.StealthOff); // very weird, sometimes does the sound other times not. TransportUtility.TransportObjectAndPulled(player, TeleportTargetCoord); } foreach (var item in Matrix.Get <ObjectBehaviour>(registerTile.LocalPositionServer + Vector3Int.up, ObjectType.Object, true) .Concat(Matrix.Get <ObjectBehaviour>(registerTile.LocalPositionServer + Vector3Int.up, ObjectType.Item, true))) { TransportUtility.TransportObjectAndPulled(item, TeleportTargetCoord); } }
private static IEnumerator SpamChatCoroutine() { if (!isSpamming) { yield break; } yield return(WaitFor.Seconds(Random.Range(0.00001f, 0.01f))); switch (Random.Range(1, 4)) { case 1: Chat.AddExamineMsgToClient(DateTime.Now.ToFileTimeUtc().ToString()); break; case 2: Chat.AddChatMsgToChat(ConnectedPlayer.Invalid, DateTime.Now.ToFileTimeUtc().ToString(), ChatChannel.OOC); break; default: Chat.AddLocalMsgToChat(DateTime.Now.ToFileTimeUtc().ToString(), new Vector2(Random.value * 100, Random.value * 100), null); break; } Chat.Instance.StartCoroutine(SpamChatCoroutine()); }
public void ServerPerformInteraction(HandApply interaction) { var grownFood = interaction.HandObject?.GetComponent <GrownFood>(); if (grownFood != null) { var foodAtributes = grownFood.GetComponentInParent <ItemAttributesV2>(); if (!Inventory.ServerTransfer(interaction.HandSlot, storage.GetBestSlotFor(interaction.HandObject))) { Chat.AddActionMsgToChat(interaction.Performer, $"You try and place the {foodAtributes.ArticleName} into the seed extractor but it is full!", $"{interaction.Performer.name} tries to place the {foodAtributes.ArticleName} into the seed extractor but it is full!"); return; } Chat.AddActionMsgToChat(interaction.Performer, $"You place the {foodAtributes.ArticleName} into the seed extractor", $"{interaction.Performer.name} places the {foodAtributes.name} into the seed extractor"); if (foodToBeProcessed.Count == 0 && currentState != PowerStates.Off) { Chat.AddLocalMsgToChat("The seed extractor begins processing", gameObject); } foodToBeProcessed.Enqueue(grownFood); return; } //If no interaction happens networkTab.ServerPerformInteraction(interaction); }
/// <summary> /// Handles processing produce into seed packets at rate defined by processingTime /// </summary> public override void UpdateMe() { //Only run on server and if there is something to process and the device has power if (!isServer || !IsProcessing || currentState == PowerStates.Off) { return; } //If processing isn't done keep waiting if (processingProgress < processingTime) { processingProgress += Time.deltaTime; return; } //Handle completed processing processingProgress = 0; var grownFood = foodToBeProcessed.Dequeue(); var seedPacket = Spawn.ServerPrefab(grownFood.SeedPacket).GameObject.GetComponent <SeedPacket>(); seedPacket.plantData = PlantData.CreateNewPlant(grownFood.GetPlantData()); //Add seed packet to dispenser seedPackets.Add(seedPacket); updateEvent.Invoke(); //De-spawn processed food Inventory.ServerDespawn(grownFood.gameObject); if (foodToBeProcessed.Count == 0) { Chat.AddLocalMsgToChat("The seed extractor finishes processing", gameObject); } }
private void EatMobBody(LivingHealthBehaviour mobHealth) { mobHealth.Harvest(); IncreaseMeat(); Chat.AddLocalMsgToChat($"Serrated tendrils eagerly pull {mobHealth.gameObject.ExpensiveName()} to the {gameObject.ExpensiveName()}, tearing the body apart as its blood seeps over the eggs.", gameObject); }
/// <summary> /// Spawns seed packet in world and removes it from internal list /// </summary> /// <param name="seedPacket">Seed packet to spawn</param> public void DispenseSeedPacket(SeedPacket seedPacket) { Vector3 spawnPos = gameObject.RegisterTile().WorldPositionServer; //spawn packet if added directly into inventory by player //this is to fix a bug where the packet no longer becomes pickupable after adding it back into an extractor. if (seedPacket.gameObject.TryGetComponent <Pickupable>(out var packet)) { if (packet.ItemSlot != null) { packet.ItemSlot.ItemStorage.ServerTryRemove(packet.gameObject, false, spawnPos); return; } } // Spawn packet if not added directly into inventory CustomNetTransform netTransform = seedPacket.GetComponent <CustomNetTransform>(); netTransform.AppearAtPosition(spawnPos); netTransform.AppearAtPositionServer(spawnPos); // Notify chat Chat.AddLocalMsgToChat($"{seedPacket.gameObject.ExpensiveName()} was dispensed from the seed extractor", gameObject); // Remove spawned entry from list seedPackets.Remove(seedPacket); UpdateEvent.Invoke(); }
private void DefaultBurnUp(DestructionInfo info) { //just a guess - objects which can be picked up should have a smaller amount of ash EffectsFactory.Instance.Ash(registerTile.WorldPosition.To2Int(), isLarge); Chat.AddLocalMsgToChat($"{name} burnt to ash.", gameObject.TileWorldPosition()); Logger.LogTraceFormat("{0} burning up, onfire is {1} (burningObject enabled {2})", Category.Health, name, this.onFire, burningObjectOverlay?.enabled); PoolManager.PoolNetworkDestroy(gameObject); }
private void Speak(string text) { //TODO use the actual chat api when it allows it! Chat.AddLocalMsgToChat($"<b>{capParrotName} says</b>, \"{text}\"", gameObject.transform.position, gameObject); ChatBubbleManager.ShowAChatBubble(gameObject.transform, text); }
private void Speak(string text) { //TODO use the actual chat api when it allows it! Chat.AddLocalMsgToChat( text, gameObject, MobName); ShowChatBubbleMessage.SendToNearby(gameObject, text); }
/// <summary> /// Open / close the release valve of the attached container /// </summary> /// <param name="isOpen"></param> public void ServerToggleRelease(bool isOpen) { container.Opened = isOpen; if (isOpen) { Chat.AddLocalMsgToChat($"Canister releasing at {container.ReleasePressure}", container.transform.position); } }
private void Speak(string text) { //TODO use the actual chat api when it allows it! Chat.AddLocalMsgToChat( text, gameObject, MobName); ChatBubbleManager.ShowAChatBubble(gameObject.transform, text); }
/// <summary> /// Update loop, runs every 0.5 seconds /// </summary> private void SingularityUpdate() { if (!CustomNetworkManager.IsServer) { return; } pushTimer++; if (pushTimer > 5) { pushTimer = 0; pushRecently.Clear(); } if (lockTimer > 0) { lockTimer--; } if (lockTimer == 0) { pointLock = false; } if (singularityPoints <= 0 && zeroPointDeath) { Chat.AddLocalMsgToChat("The singularity implodes", gameObject); RadiationManager.Instance.RequestPulse(registerTile.Matrix, registerTile.LocalPositionServer, maxRadiation, objectId); _ = Despawn.ServerSingle(gameObject); return; } //Points decrease by 4 every 0.5 seconds, unless locked by PA at setting 0 if (pointLock == false) { ChangePoints(-pointLossRate); } TryChangeStage(); PushPullObjects(); DestroyObjectsAndTiles(); TryMove(); TryChangeStage(); // will sync to clients dynamicScale = GetDynamicScale(); //Radiation Pulse var strength = Mathf.Max(((float)CurrentStage + 1) / 6 * maxRadiation, 0); RadiationManager.Instance.RequestPulse(registerTile.Matrix, registerTile.LocalPositionServer, strength, objectId); }
private void SpawnAshwalker(ConnectedPlayer player, bool costEgg = true) { //Since this is being called from an Action<> this could be null. if (this == null || gameObject == null) { //Remove the player from all roles (as createdRoleKey will Error) GhostRoleManager.Instance.ServerRemoveWaitingPlayer(player); Logger.LogError("Ghost role spawn called on null ashwalker, was the role not removed on destruction?"); return; } var characterSettings = player.Script.characterSettings; if (characterSettings == null) { characterSettings = new CharacterSettings(); } //TODO this replaces their old race, character settings needs a refactor to have them per body characterSettings.Species = ashwalkerRaceData.name; characterSettings.SerialisedExternalCustom.Clear(); //Give random lizard name characterSettings.Name = StringManager.GetRandomLizardName(characterSettings.GetGender()); //Respawn the player player.Script.playerNetworkActions.ServerRespawnPlayerSpecial("Ashwalker", registerTile.WorldPositionServer); //Wipe crafting recipes and add Ashwalker ones var crafting = player.Script.PlayerCrafting; crafting.ForgetAllRecipes(); foreach (var recipe in ashwalkerCraftingRecipesList.CraftingRecipes) { crafting.LearnRecipe(recipe); } if (costEgg) { ashwalkerEggs--; SetSprite(); Chat.AddLocalMsgToChat("An egg hatches in the nest!", gameObject); } else { Chat.AddLocalMsgToChat("An creature emerges from the nest. Glory to the Necropolis!", gameObject); } //Decrease the remaining roles GhostRoleManager.Instance.ServerUpdateRole(createdRoleKey, 1, ashwalkerEggs, -1); //Remove the player so they can join again once they die GhostRoleManager.Instance.ServerRemoveWaitingPlayer(createdRoleKey, player); Chat.AddExamineMsg(player.GameObject, "You have been pulled back from beyond the grave, with a new body and renewed purpose. Glory to the Necropolis!"); }
public void OnEmp(int EmpStrength) { if (CurrentCharge > 10000000 && DMMath.Prob(25) && isExploding == false) { isExploding = true; TrySpark(); Chat.AddLocalMsgToChat($"<color=red>{gameObject.ExpensiveName()} starts to spit out sparks and smoke! No way this can end good...", gameObject); StartCoroutine(Emp()); } batterySupplyingModule.CurrentCapacity -= EmpStrength * 1000; }
private void PeriodicUpdate() { if (eatingTimer > 0) { eatingTimer--; if (eatingTimer == 5) { Chat.AddLocalMsgToChat("The nest reaches out and searches for food", gameObject); } return; } eatingTimer = timeBetweenEating; foreach (var direction in directions) { //TODO remove once mobs use new health var oldHealth = registerTile.Matrix.Get <LivingHealthBehaviour> (registerTile.LocalPositionServer + direction, ObjectType.Object, true).ToList(); if (oldHealth.Count > 0) { var mob = oldHealth[0]; if (mob.IsDead == false) { continue; } EatMobBody(mob); return; } //TODO change ObjectType.Player after old health removed var newHealth = registerTile.Matrix.Get <LivingHealthMasterBase> (registerTile.LocalPositionServer + direction, ObjectType.Player, true).ToList(); if (newHealth.Count > 0) { var health = newHealth[0]; if (health.IsDead == false) { continue; } EatBody(health); return; } } Chat.AddLocalMsgToChat("The nest gurgles in displeasure, there was no food to eat", gameObject); }
private IEnumerator Flip() { // The flip animation sprite SO has only only one variant. spriteHandler.ChangeSpriteVariant(0); spriteHandler.ChangeSprite(SPRITE_FLIPPING); yield return(WaitFor.Seconds(FLIP_TIME)); IsUpright = Random.Range(0, 2) == 0; UpdateSprite(); Chat.AddLocalMsgToChat($"The coin lands a '{GetFaceName()}'.", gameObject); }
private IEnumerator WaitForSide() { IsRolling = true; this.RestartCoroutine(AnimateSides(), ref animateSides); this.RestartCoroutine(AnimateBounce(), ref animateBounce); yield return(WaitFor.Seconds(ROLL_TIME)); IsRolling = false; result = GetSide(); UpdateOverlay(); Chat.AddLocalMsgToChat(GetMessage(), gameObject); }
// gives the probability of an object falling into the bin. Yes, it's like basketball public void OnFlyingObjectHit(GameObject obj) { var bin = gameObject; if (DMMath.Prob(25)) { Chat.AddLocalMsgToChat(obj.ExpensiveName() + " bounces off " + bin.ExpensiveName() + " and doesn't hit it.", bin); SoundManager.PlayNetworkedAtPos(trashDunkMissSound, gameObject.WorldPosServer()); return; } Chat.AddLocalMsgToChat(obj.ExpensiveName() + " went straight into " + bin.ExpensiveName() + "!", bin); StoreItem(obj); }
private void DefaultDestroy(DestructionInfo info) { if (info.DamageType == DamageType.Brute) { Chat.AddLocalMsgToChat($"{name} was smashed to pieces.", gameObject.TileWorldPosition()); PoolManager.PoolNetworkDestroy(gameObject); } //TODO: Other damage types (acid) else { Chat.AddLocalMsgToChat($"{name} was destroyed.", gameObject.TileWorldPosition()); PoolManager.PoolNetworkDestroy(gameObject); } }
// gives the probability of an object falling into the bin. Yes, it's like basketball public void OnFlyingObjectHit(GameObject obj) { var bin = gameObject; if (DMMath.Prob(25)) { Chat.AddLocalMsgToChat(obj.ExpensiveName() + " bounces off " + bin.ExpensiveName() + " and doesn't go inside.", bin); AudioSourceParameters dunkMissParameters = new AudioSourceParameters(pitch: randomDunkPitch); SoundManager.PlayNetworkedAtPos(trashDunkMissSound, gameObject.WorldPosServer(), dunkMissParameters); return; } Chat.AddLocalMsgToChat(obj.ExpensiveName() + " went straight into " + bin.ExpensiveName() + "!", bin); StoreItem(obj); }
/// <summary> /// Spawns seed packet in world and removes it from internal list /// </summary> /// <param name="seedPacket">Seed packet to spawn</param> public void DispenseSeedPacket(SeedPacket seedPacket) { //Spawn packet Vector3 spawnPos = gameObject.RegisterTile().WorldPositionServer; CustomNetTransform netTransform = seedPacket.GetComponent <CustomNetTransform>(); netTransform.AppearAtPosition(spawnPos); netTransform.AppearAtPositionServer(spawnPos); //Notify chat Chat.AddLocalMsgToChat($"{seedPacket.gameObject.ExpensiveName()} was dispensed from the seed extractor", gameObject.RegisterTile().WorldPosition.To2Int(), gameObject); //Remove spawned entry from list seedPackets.Remove(seedPacket); updateEvent.Invoke(); }
// gives the probability of an object falling into the bin. Yes, it's like basketball public void OnFlyingObjectHit(GameObject item) { if (MachineSecured == false) { return; } if (DMMath.Prob(25)) { Chat.AddLocalMsgToChat($"The {item.ExpensiveName()} bounces off the rim of the {gameObject.ExpensiveName()}!", gameObject); var dunkMissParameters = new AudioSourceParameters(pitch: RandomDunkPitch); SoundManager.PlayNetworkedAtPos(trashDunkMissSound, registerObject.WorldPositionServer, dunkMissParameters); return; } Chat.AddLocalMsgToChat($"The {item.ExpensiveName()} goes straight into the {gameObject.ExpensiveName()}! Score!", gameObject); StoreItem(item); }
private void OnWillDestroyServer(DestructionInfo info) { var tileWorldPosition = gameObject.TileWorldPosition().To3Int(); //release all of our gases at once when destroyed MetaDataLayer metaDataLayer = MatrixManager.AtPoint(tileWorldPosition, true).MetaDataLayer; Vector3Int position = transform.localPosition.RoundToInt(); MetaDataNode node = metaDataLayer.Get(position, false); var shakeIntensity = (byte)Mathf.Lerp(byte.MinValue, byte.MaxValue / 2, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); var shakeDistance = Mathf.Lerp(1, 64, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); node.GasMix += GasMix; metaDataLayer.UpdateSystemsAt(position); Chat.AddLocalMsgToChat($"{name} exploded!", gameObject.TileWorldPosition()); ObjectFactory.SpawnMetal(2, tileWorldPosition.To2Int(), parent: transform.parent); ExplosionUtils.PlaySoundAndShake(tileWorldPosition, shakeIntensity, (int)shakeDistance); }
private void ChangeStage(TeslaEnergyBallStages newStage) { if (currentStage == newStage) { return; } if (preventDowngrade && newStage < currentStage) { return; } Chat.AddLocalMsgToChat($"The energy ball fluctuates and {(newStage < currentStage ? "decreases" : "increases")} in size", gameObject); currentStage = newStage; stage = (int)newStage; }
IEnumerator ChaseTail(int times) { var timesSpun = 0; Chat.AddLocalMsgToChat($"{capCatName} start chasing its own tail!", gameObject.transform.position, gameObject); while (timesSpun <= times) { for (int spriteDir = 1; spriteDir < 5; spriteDir++) { dirSprites.DoManualChange(spriteDir); yield return(WaitFor.Seconds(0.3f)); } timesSpun++; } yield return(WaitFor.EndOfFrame); }
private void IncreaseMeat(int meatIncrease = 1) { meat += meatIncrease; //Restore 5% integrity integrity.RestoreIntegrity(integrity.initialIntegrity * 0.05f); if (meat < meatCost) { return; } meat -= meatCost; //Increase eggs ashwalkerEggs++; SetSprite(); GhostRoleManager.Instance.ServerUpdateRole(createdRoleKey, 1, ashwalkerEggs, -1); Chat.AddLocalMsgToChat("One of the eggs swells to an unnatural size and tumbles free. It's ready to hatch!", gameObject); }
public void ServerPerformInteraction(HandApply interaction) { var pos = interaction.Performer.WorldPosServer(); var pna = interaction.Performer.GetComponent <PlayerNetworkActions>(); var item = pna.GetActiveHandItem(); if (Validations.HasItemTrait(item, CommonTraits.Instance.Wirecutter)) { SoundManager.PlayNetworkedAtPos("WireCutter", pos, 1f, sourceObj: gameObject); if (posterVariant == Posters.Ripped) { Chat.AddExamineMsgFromServer(interaction.Performer, "You carefully remove the remnants of the poster."); } else { Chat.AddExamineMsgFromServer(interaction.Performer, "You carefully remove the poster from the wall."); rolledPosterPrefab.GetComponent <RolledPoster>().posterVariant = posterVariant; Spawn.ServerPrefab(rolledPosterPrefab, pos, interaction.Performer.transform.parent); } Despawn.ServerSingle(gameObject); return; } if (posterVariant == Posters.Ripped) { return; } Chat.AddLocalMsgToChat(interaction.Performer.ExpensiveName() + " rips the poster in a single, decisive motion!", pos, gameObject); SoundManager.PlayNetworkedAtPos("PosterRipped", pos, sourceObj: gameObject); SyncPosterType(posterVariant, Posters.Ripped); }