public Drone(IMyEntity ent) { var ship = (IMyCubeGrid)ent; Ship = ship; var lstSlimBlock = new List <IMySlimBlock>(); GridTerminalSystem = MyAPIGateway.TerminalActionsHelper.GetTerminalSystemForGrid(ship); //If it has any type of cockipt ship.GetBlocks(lstSlimBlock, (x) => x.FatBlock is Sandbox.ModAPI.IMyRemoteControl); FindWeapons(); SetupActions(); //If no cockpit the ship is either no ship or is broken. if (lstSlimBlock.Count != 0) { //Make the controls be the cockpit ShipControls = lstSlimBlock[0].FatBlock as IMyControllableEntity; #region Activate Beacons && Antennas //Maximise radius on antennas and beacons. lstSlimBlock.Clear(); ship.GetBlocks(lstSlimBlock, (x) => x.FatBlock is Sandbox.ModAPI.IMyRadioAntenna); foreach (var block in lstSlimBlock) { Sandbox.ModAPI.IMyRadioAntenna antenna = (Sandbox.ModAPI.IMyRadioAntenna)block.FatBlock; if (antenna != null) { //antenna.GetActionWithName("SetCustomName").Apply(antenna, new ListReader<TerminalActionParameter>(new List<TerminalActionParameter>() { TerminalActionParameter.Get("Combat Drone " + _manualGats.Count) })); antenna.SetValueFloat("Radius", 10000);//antenna.GetMaximum<float>("Radius")); _blockOn.Apply(antenna); } } lstSlimBlock = new List <IMySlimBlock>(); ship.GetBlocks(lstSlimBlock, (x) => x.FatBlock is Sandbox.ModAPI.IMyBeacon); foreach (var block in lstSlimBlock) { Sandbox.ModAPI.IMyBeacon beacon = (Sandbox.ModAPI.IMyBeacon)block.FatBlock; if (beacon != null) { beacon.SetValueFloat("Radius", 10000);//beacon.GetMaximum<float>("Radius")); _blockOn.Apply(beacon); } } #endregion //SetWeaponPower(true); //AmmoManager.ReloadReactors(_allReactors); //AmmoManager.ReloadGuns(_manualGats); ship.GetBlocks(lstSlimBlock, x => x is IMyEntity); List <IMyTerminalBlock> allTerminalBlocks = new List <IMyTerminalBlock>(); GridTerminalSystem.GetBlocksOfType <IMyCubeBlock>(allTerminalBlocks); HealthBlockBase = allTerminalBlocks.Count; if (ShipControls != null) { navigation = new ThrusterGyroControls(ship, ShipControls); _ownerId = ((Sandbox.ModAPI.IMyTerminalBlock)ShipControls).OwnerId; tc = new TargetingControls(Ship, _ownerId); } } Ship.OnBlockAdded += RecalcMaxHp; myNumber = numDrones; numDrones++; }
private void updateFoodLogic() { float elapsedMinutes = (float)(mTimer.Elapsed.Seconds / 60); //float CurPlayerHealth = -1f; bool ChangedStance = false; MyObjectBuilder_Character character; MyCharacterMovementEnum curmove = MyCharacterMovementEnum.Sitting; foreach (var player in _players) { if (String.IsNullOrWhiteSpace(player.Controller?.ControlledEntity?.Entity?.DisplayName)) { PlayerData playerData = _playerDataStorage.Retrieve(player); Logging.Instance.WriteLine(playerData.ToString() + "Loaded to Server"); IMyEntity entity = player.Controller.ControlledEntity.Entity; entity = GetCharacterEntity(entity); // //MyAPIGateway.Utilities.ShowMessage("DEBUG", "Character: " + entity.DisplayName); // gets me player name float currentModifier = 1f; float fatigueRate = 0f; bool dead = false; bool forceEating = false; float recycleBonus = 1f; bool fatigueBonus = false; bool hungerBonus = false; bool thirstBonus = false; // if we were under the effects of a bonus, keep it until we no longer are fatigueBonus = playerData.fatigue > Config.MaxValue; thirstBonus = playerData.thirst > Config.MaxValue; hungerBonus = playerData.hunger > Config.MaxValue; if (entity is IMyCharacter) { character = entity.GetObjectBuilder() as MyObjectBuilder_Character; //MyAPIGateway.Utilities.ShowMessage("DEBUG", "State: " + character.MovementState); if (playerData.Entity == null || playerData.Entity.Closed || playerData.Entity.EntityId != entity.EntityId) { bool bReset = false; if (!playerData.loaded) { bReset = true; playerData.loaded = true; } else if ((playerData.Entity != null) && (playerData.Entity != entity)) { bReset = true; } if (bReset) { playerData.hunger = Config.StartingHunger; playerData.thirst = Config.StartingThirst; playerData.fatigue = Config.StartingFatigue; } playerData.Entity = entity; } //MyAPIGateway.Utilities.ShowMessage("DEBUG", "State: " + character.MovementState + ":" + playerData.LastMovement); ChangedStance = playerData.LastMovement != character.MovementState; curmove = character.MovementState; switch (character.MovementState) // this should be all of them.... { case MyCharacterMovementEnum.Sitting: IMyCubeBlock cb = player.Controller.ControlledEntity.Entity as IMyCubeBlock; //cb.DisplayNameText is name of individual block, cb.DefinitionDisplayNameText is name of block type currentModifier = Config.DefaultModifier; fatigueRate = Config.FatigueSitting; // special case: we may be interacting with a bed, a lunchroom seat or treadmill, so let's String seatmodel = cb.DefinitionDisplayNameText.ToLower(); String seatname = cb.DisplayNameText.ToLower(); if (seatmodel.Contains("cryo")) // you're in a cryopd not an oxygen bed { currentModifier = 0.0000125f; fatigueRate = 0.0000125f; } else if (seatmodel.Contains("treadmill")) { currentModifier = RUNNING_MODIFIER; // jog... fatigueRate = FATIGUE_RUNNING / 2.5f; // but pace yourself } else if (seatmodel.Contains("bed") || seatmodel.Contains("bunk")) { currentModifier = DEFAULT_MODIFIER / 2f; // nap time! Needs are reduced. fatigueRate = FATIGUE_SITTING * 3f; // nap time! Rest is greatly sped up. fatigueBonus |= !ChangedStance; // longer nap? OK, allow for extra resting } else if (seatmodel.Contains("toilet") && ChangedStance) { forceEating = true; // also forces defecation, so this makes sense. but use changedstance to do it only once. recycleBonus = 1.5f; } else if (seatname.Contains("noms")) { forceEating = true; // also forces crapping, fortunately the suit takes care of it. Eat continuously while sitting. hungerBonus |= playerData.hunger > Config.MaxValue * 0.99; // get to 100% first, then apply bonus. thirstBonus |= playerData.thirst > Config.MaxValue * 0.99; // get to 100% first, then apply bonus. } break; case MyCharacterMovementEnum.Flying: currentModifier = FLYING_MODIFIER; fatigueRate = FATIGUE_FLYING; // operating a jetpack is surprisingly hard break; case MyCharacterMovementEnum.Falling: currentModifier = FLYING_MODIFIER; fatigueRate = FATIGUE_WALKING; // change nothing for the first iteration (prevents jump exploit) if (!ChangedStance) { fatigueRate = FATIGUE_STANDING; // freefall is actually relaxing when you are used to it. A professional space engineer would be. } break; case MyCharacterMovementEnum.Crouching: case MyCharacterMovementEnum.CrouchRotatingLeft: case MyCharacterMovementEnum.CrouchRotatingRight: currentModifier = DEFAULT_MODIFIER; fatigueRate = FATIGUE_CROUCHING; break; case MyCharacterMovementEnum.Standing: case MyCharacterMovementEnum.RotatingLeft: case MyCharacterMovementEnum.RotatingRight: currentModifier = DEFAULT_MODIFIER; fatigueRate = FATIGUE_STANDING; break; case MyCharacterMovementEnum.CrouchWalking: case MyCharacterMovementEnum.CrouchBackWalking: case MyCharacterMovementEnum.CrouchStrafingLeft: case MyCharacterMovementEnum.CrouchStrafingRight: case MyCharacterMovementEnum.CrouchWalkingRightFront: case MyCharacterMovementEnum.CrouchWalkingRightBack: case MyCharacterMovementEnum.CrouchWalkingLeftFront: case MyCharacterMovementEnum.CrouchWalkingLeftBack: currentModifier = RUNNING_MODIFIER; fatigueRate = FATIGUE_RUNNING; // doing the duckwalk is more tiring than walking: try it if you don't believe me break; case MyCharacterMovementEnum.Walking: case MyCharacterMovementEnum.BackWalking: case MyCharacterMovementEnum.WalkStrafingLeft: case MyCharacterMovementEnum.WalkStrafingRight: case MyCharacterMovementEnum.WalkingRightFront: case MyCharacterMovementEnum.WalkingRightBack: case MyCharacterMovementEnum.WalkingLeftFront: case MyCharacterMovementEnum.WalkingLeftBack: currentModifier = DEFAULT_MODIFIER; fatigueRate = FATIGUE_WALKING; break; case MyCharacterMovementEnum.LadderUp: currentModifier = RUNNING_MODIFIER; fatigueRate = FATIGUE_RUNNING; break; case MyCharacterMovementEnum.LadderDown: currentModifier = DEFAULT_MODIFIER; fatigueRate = FATIGUE_WALKING; break; case MyCharacterMovementEnum.Running: case MyCharacterMovementEnum.Backrunning: case MyCharacterMovementEnum.RunStrafingLeft: case MyCharacterMovementEnum.RunStrafingRight: case MyCharacterMovementEnum.RunningRightFront: case MyCharacterMovementEnum.RunningRightBack: case MyCharacterMovementEnum.RunningLeftBack: case MyCharacterMovementEnum.RunningLeftFront: currentModifier = RUNNING_MODIFIER; fatigueRate = FATIGUE_RUNNING; break; case MyCharacterMovementEnum.Sprinting: case MyCharacterMovementEnum.Jump: currentModifier = SPRINTING_MODIFIER; fatigueRate = FATIGUE_SPRINTING; break; case MyCharacterMovementEnum.Died: currentModifier = DEFAULT_MODIFIER; // unused, but let's have them fatigueRate = FATIGUE_STANDING; // unused, but let's have them dead = true; // for death recovery logic break; } playerData.LastMovement = character.MovementState; // track delta } else if (playerData.Entity != null || !playerData.Entity.Closed) { entity = playerData.Entity; } // Sanity checks if (hungerBonus) { if (playerData.hunger > Config.MaxValue * FOOD_BONUS) { playerData.hunger = Config.MaxValue * FOOD_BONUS; } } else { if (playerData.hunger > Config.MaxValue) { playerData.hunger = Config.MaxValue; } } if (thirstBonus) { if (playerData.thirst > Config.MaxValue * DRINK_BONUS) { playerData.thirst = Config.MaxValue * DRINK_BONUS; } } else { if (playerData.thirst > Config.MaxValue) { playerData.thirst = Config.MaxValue; } } // Cause needs if (FATIGUE_ENABLED) { playerData.fatigue += (fatigueRate * FOOD_LOGIC_SKIP_TICKS / 60 * 20); // / 15); playerData.fatigue = Math.Max(playerData.fatigue, MIN_VALUE); if (fatigueBonus) { playerData.fatigue = Math.Min(playerData.fatigue, Config.MaxValue * REST_BONUS); } else { playerData.fatigue = Math.Min(playerData.fatigue, Config.MaxValue); } } else { playerData.fatigue = 9001f; } if (playerData.fatigue <= 0) { // fatigue consequences // at 0, start causing extra thirst // at specified, force walk instead of run (unless overriding by sprinting) // at specified, force crouch, and do damage flashes // at specified, breathing reflex / mess with helmet, and do a bit of actual damage (just in case thirst isn't already causing it) // at specified, cause heart attack if (playerData.fatigue <= (0.00f * MIN_VALUE)) { if (EXTRA_THIRST_FROM_FATIGUE > 0) { // positive: pile on to thirst, per second playerData.thirst -= (EXTRA_THIRST_FROM_FATIGUE * FOOD_LOGIC_SKIP_TICKS / 60); } else // negative: multiply modifier { currentModifier *= -EXTRA_THIRST_FROM_FATIGUE; } } if (playerData.fatigue <= (FATIGUE_LEVEL_FORCEWALK * MIN_VALUE)) { // force player to walk if they were running switch (curmove) { case MyCharacterMovementEnum.Sprinting: case MyCharacterMovementEnum.Running: case MyCharacterMovementEnum.Backrunning: case MyCharacterMovementEnum.RunStrafingLeft: case MyCharacterMovementEnum.RunStrafingRight: case MyCharacterMovementEnum.RunningRightFront: case MyCharacterMovementEnum.RunningRightBack: case MyCharacterMovementEnum.RunningLeftBack: case MyCharacterMovementEnum.RunningLeftFront: VRage.Game.ModAPI.Interfaces.IMyControllableEntity ce = player.Controller.ControlledEntity.Entity as VRage.Game.ModAPI.Interfaces.IMyControllableEntity; ce.SwitchWalk(); break; } } if (playerData.fatigue <= (FATIGUE_LEVEL_FORCECROUCH * MIN_VALUE)) { bool iscrouching = false; switch (curmove) { case MyCharacterMovementEnum.Crouching: case MyCharacterMovementEnum.CrouchWalking: case MyCharacterMovementEnum.CrouchBackWalking: case MyCharacterMovementEnum.CrouchStrafingLeft: case MyCharacterMovementEnum.CrouchStrafingRight: case MyCharacterMovementEnum.CrouchWalkingRightFront: case MyCharacterMovementEnum.CrouchWalkingRightBack: case MyCharacterMovementEnum.CrouchWalkingLeftFront: case MyCharacterMovementEnum.CrouchWalkingLeftBack: iscrouching = true; break; } if (!iscrouching) { VRage.Game.ModAPI.Interfaces.IMyControllableEntity ce = player.Controller.ControlledEntity.Entity as VRage.Game.ModAPI.Interfaces.IMyControllableEntity; ce.Crouch(); // force player to crouch } } if (playerData.fatigue <= (FATIGUE_LEVEL_HELMET * MIN_VALUE)) { VRage.Game.ModAPI.Interfaces.IMyControllableEntity ce = player.Controller.ControlledEntity.Entity as VRage.Game.ModAPI.Interfaces.IMyControllableEntity; ce.SwitchHelmet(); // force player to switch helmet, panic reaction from trying to catch breath var destroyable = entity as IMyDestroyableObject; destroyable.DoDamage(0.001f, MyStringHash.GetOrCompute("Fatigue"), true); // starting to hurt } if (playerData.fatigue <= (FATIGUE_LEVEL_NOHEALING * MIN_VALUE)) { var destroyable = entity as IMyDestroyableObject; destroyable.DoDamage(0.001f, MyStringHash.GetOrCompute("Fatigue"), true); // starting to hurt if (IsAutohealingOn) // fatigued? no autohealing, either. { const float HealthTick = 100f / 240f * FOOD_LOGIC_SKIP_TICKS / 60f; destroyable.DoDamage(HealthTick, MyStringHash.GetOrCompute("Testing"), false); } } if (playerData.fatigue <= (FATIGUE_LEVEL_HEARTATTACK * MIN_VALUE)) { var destroyable = entity as IMyDestroyableObject; destroyable.DoDamage(1000f, MyStringHash.GetOrCompute("Fatigue"), true); // sudden, but very avoidable, heart attack ;) } } if (playerData.thirst > MIN_VALUE) { playerData.thirst -= elapsedMinutes * mThirstPerMinute * currentModifier; playerData.thirst = Math.Max(playerData.thirst, MIN_VALUE); } if (playerData.hunger > MIN_VALUE) { playerData.hunger -= elapsedMinutes * mHungerPerMinute * currentModifier; playerData.hunger = Math.Max(playerData.hunger, MIN_VALUE); } // Try to meet needs if (playerData.hunger < (Config.MaxValue * HUNGRY_WHEN) || forceEating) { playerEatSomething(entity, playerData, hungerBonus?Config.MaxValue * 1.25f:Config.MaxValue, recycleBonus); } if (playerData.thirst < (Config.MaxValue * THIRSTY_WHEN) || forceEating) { playerDrinkSomething(entity, playerData, thirstBonus?Config.MaxValue * 1.25f:Config.MaxValue, recycleBonus); } // Cause damage if needs are unmet if (playerData.thirst <= 0) { var destroyable = entity as IMyDestroyableObject; if (DAMAGE_SPEED_THIRST > 0) { destroyable.DoDamage((IsAutohealingOn ? (DAMAGE_SPEED_THIRST + 1f) : DAMAGE_SPEED_THIRST), MyStringHash.GetOrCompute("Thirst"), true); } else { destroyable.DoDamage(((IsAutohealingOn ? (-DAMAGE_SPEED_THIRST + 1f) : -DAMAGE_SPEED_THIRST) + DAMAGE_SPEED_THIRST * playerData.thirst), MyStringHash.GetOrCompute("Thirst"), true); } } if (playerData.hunger <= 0) { var destroyable = entity as IMyDestroyableObject; if (DAMAGE_SPEED_HUNGER > 0) { destroyable.DoDamage((IsAutohealingOn ? (DAMAGE_SPEED_HUNGER + 1f) : DAMAGE_SPEED_HUNGER), MyStringHash.GetOrCompute("Hunger"), true); } else { destroyable.DoDamage(((IsAutohealingOn ? (-DAMAGE_SPEED_HUNGER + 1f) : -DAMAGE_SPEED_HUNGER) + DAMAGE_SPEED_HUNGER * playerData.hunger), MyStringHash.GetOrCompute("Hunger"), true); } } /* * * * character = entity.GetObjectBuilder(false) as MyObjectBuilder_Character; * if (character.Health == null) // ok, so the variable exists, but it's always null for some reason? * CurPlayerHealth = 101f; * else * CurPlayerHealth = (float) (character.Health); * * if (IsAutohealingOn && CurPlayerHealth < 70f) * { * const float HealthTick = 100f / 240f * FOOD_LOGIC_SKIP_TICKS / 60f; * var destroyable = entity as IMyDestroyableObject; * destroyable.DoDamage(HealthTick, MyStringHash.GetOrCompute("Testing"), false); * } */ if (dead && DEATH_RECOVERY > 0.0) { MyInventoryBase inventory = ((MyEntity)entity).GetInventoryBase(); if (playerData.hunger > 0) { inventory.AddItems((MyFixedPoint)((1f / Config.MaxValue) * DEATH_RECOVERY * (playerData.hunger)), new MyObjectBuilder_Ore() { SubtypeName = "Organic" }); } if (playerData.thirst > 0) { inventory.AddItems((MyFixedPoint)((1f / Config.MaxValue) * DEATH_RECOVERY * (playerData.thirst)), new MyObjectBuilder_Ingot() { SubtypeName = "GreyWater" }); } } //Sends data from Server.cs to Client.cs string message = MyAPIGateway.Utilities.SerializeToXML <PlayerData>(playerData); Logging.Instance.WriteLine(("Message sent from Server.cs to Client.cs: " + message)); MyAPIGateway.Multiplayer.SendMessageTo( 1337, Encoding.Unicode.GetBytes(message), player.SteamUserId ); } } // Reinitialize the timer mTimer = new MyGameTimer(); }