public static void MineVegetable(VegeMined packet) { PlanetData planet = GameMain.galaxy?.PlanetById(packet.PlanetID); if (planet == null) { return; } if (packet.isVegetable) // Trees, rocks, leaves, etc { VegeData vData = (VegeData)planet.factory?.GetVegeData(packet.MiningID); VegeProto vProto = LDB.veges.Select((int)vData.protoId); if (vProto != null && planet.id == GameMain.localPlanet?.id) { VFEffectEmitter.Emit(vProto.MiningEffect, vData.pos, vData.rot); VFAudio.Create(vProto.MiningAudio, null, vData.pos, true); } planet.factory?.RemoveVegeWithComponents(vData.id); } else // veins { VeinData vData = (VeinData)planet.factory?.GetVeinData(packet.MiningID); VeinProto vProto = LDB.veins.Select((int)vData.type); if (vProto != null) { if (planet.factory?.veinPool[packet.MiningID].amount > 0) { VeinData[] vPool = planet.factory?.veinPool; PlanetData.VeinGroup[] vGroups = planet.factory?.planet.veinGroups; long[] vAmounts = planet.veinAmounts; vPool[packet.MiningID].amount -= 1; vGroups[(int)vData.groupIndex].amount -= 1; vAmounts[(int)vData.type] -= 1; if (planet.id == GameMain.localPlanet?.id) { VFEffectEmitter.Emit(vProto.MiningEffect, vData.pos, Maths.SphericalRotation(vData.pos, 0f)); VFAudio.Create(vProto.MiningAudio, null, vData.pos, true); } } else { PlanetData.VeinGroup[] vGroups = planet.factory?.planet.veinGroups; vGroups[vData.groupIndex].count -= 1; if (planet.id == GameMain.localPlanet?.id) { VFEffectEmitter.Emit(vProto.MiningEffect, vData.pos, Maths.SphericalRotation(vData.pos, 0f)); VFAudio.Create(vProto.MiningAudio, null, vData.pos, true); } planet.factory?.RemoveVeinWithComponents(vData.id); } } } }
public override void ProcessPacket(VegeMinedPacket packet, NebulaConnection conn) { if (GameMain.galaxy.PlanetById(packet.PlanetId)?.factory != null && GameMain.galaxy.PlanetById(packet.PlanetId)?.factory?.vegePool != null) { using (Multiplayer.Session.Planets.IsIncomingRequest.On()) { PlanetFactory factory = GameMain.galaxy.PlanetById(packet.PlanetId)?.factory; if (packet.Amount == 0 && factory != null) { if (packet.IsVein) { VeinData veinData = factory.GetVeinData(packet.VegeId); VeinProto veinProto = LDB.veins.Select((int)veinData.type); factory.RemoveVeinWithComponents(packet.VegeId); if (veinProto != null) { VFEffectEmitter.Emit(veinProto.MiningEffect, veinData.pos, Maths.SphericalRotation(veinData.pos, 0f)); VFAudio.Create(veinProto.MiningAudio, null, veinData.pos, true, 0, -1, -1L); } } else { VegeData vegeData = factory.GetVegeData(packet.VegeId); VegeProto vegeProto = LDB.veges.Select(vegeData.protoId); factory.RemoveVegeWithComponents(packet.VegeId); if (vegeProto != null) { VFEffectEmitter.Emit(vegeProto.MiningEffect, vegeData.pos, Maths.SphericalRotation(vegeData.pos, 0f)); VFAudio.Create(vegeProto.MiningAudio, null, vegeData.pos, true, 0, -1, -1L); } } } else if (factory != null) { VeinData veinData = factory.GetVeinData(packet.VegeId); PlanetData.VeinGroup[] veinGroups = factory.planet.veinGroups; short groupIndex = veinData.groupIndex; // must be a vein/oil patch (i think the game treats them same now as oil patches can run out too) factory.veinPool[packet.VegeId].amount = packet.Amount; factory.planet.veinAmounts[(int)veinData.type] -= 1L; veinGroups[groupIndex].amount = veinGroups[groupIndex].amount - 1L; } else { Log.Warn("Received VegeMinedPacket but could not do as i was told :C"); } } } }
public static void MechaDroneLogic_UpdateTargets_Prefix(MechaDroneLogic __instance, Player ___player) { if (___player.factory != null) { if (GameMain.data.hidePlayerModel) { if (configEnableDebug) { Logger.LogInfo("Skipping because player model is hidden. This is needed for compatability with the Render Distance mod."); } UpdateTipText("(Player hidden.)"); return; } if (!configEnableMod.Value) { if (configEnableDebug) { Logger.LogInfo("Skipping because mod is disabled."); } return; } if (___player.movementState == EMovementState.Sail) { if (configEnableDebug) { Logger.LogInfo("Skipping because movement state is Sail."); } UpdateTipText("(Waiting while Sailing.)"); RecallClearingDrones(); return; } if (___player.movementState == EMovementState.Drift && !configEnableClearingWhileDrifting) { if (configEnableDebug) { Logger.LogInfo("Skipping while drifting."); } UpdateTipText("(Waiting while Drifting.)"); return; } if (___player.movementState == EMovementState.Fly && !configEnableClearingWhileFlying) { if (configEnableRecallWhileFlying) { if (configEnableDebug) { Logger.LogInfo("Recalling drones."); } RecallClearingDrones(); } else if (configEnableDebug) { Logger.LogInfo("Skipping while flying."); } UpdateTipText("(Waiting while Flying.)"); return; } if (___player.mecha.coreEnergy < ___player.mecha.droneEjectEnergy) { if (configEnableDebug) { Logger.LogInfo("Skipping because of insufficient mecha energy to eject a drone."); } UpdateTipText("(Waiting for ejection energy.)"); return; } if ((___player.planetData.type == EPlanetType.None && !configEnableClearingPlanetGeneric) || (___player.planetData.type == EPlanetType.Vocano && !configEnableClearingPlanetVocano) || (___player.planetData.type == EPlanetType.Ocean && !configEnableClearingPlanetOcean) || (___player.planetData.type == EPlanetType.Desert && !configEnableClearingPlanetDesert) || (___player.planetData.type == EPlanetType.Ice && !configEnableClearingPlanetIce)) { if (configEnableDebug) { Logger.LogInfo("Skipping planet type " + ___player.planetData.type.ToString()); } UpdateTipText("(Waiting on this planet type.)"); return; } int totalDroneTaskingCount = getTotalDroneTaskingCount(); if (totalDroneTaskingCount >= Math.Min(configMaxClearingDroneCount, ___player.mecha.droneCount)) { if (configEnableDebug) { var sbc = new StringBuilder(); sbc.AppendFormat("Skipping due to number of drone assignments: totalDroneTaskingCount={0}, configMaxClearingDroneCount={1}, player.mecha.droneCount={2}, player.mecha.idleDroneCount={3}", totalDroneTaskingCount, configMaxClearingDroneCount, ___player.mecha.droneCount, ___player.mecha.idleDroneCount); Logger.LogInfo(sbc.ToString()); } UpdateTipText("(Available drones assigned.)"); return; } if (___player.mecha.coreEnergy / ___player.mecha.coreEnergyCap < configReservedPower) { if (configEnableDebug) { Logger.LogInfo("Skipping due to low power."); } UpdateTipText("(Waiting for energy.)"); return; } if (configCollectResourcesFlag) // ... check configReservedInventorySpace { uint numEmptyInventorySlots = 0; for (int gridIdx = 0; gridIdx < ___player.package.size; ++gridIdx) { if (___player.package.grids[gridIdx].count == 0) { numEmptyInventorySlots++; } } if (numEmptyInventorySlots < configReservedInventorySpace) { if (configEnableDebug) { Logger.LogInfo("Too few inventory slots"); } UpdateTipText("(Waiting for inventory space.)"); return; } } float closestVegeDistance = ___player.mecha.buildArea * configLimitClearingDistance * 2; int closestVegeId = -1; foreach (VegeData vegeData in ___player.factory.vegePool) { VegeProto vegeProto = LDB.veges.Select((int)vegeData.protoId); // vegeProto.Type == EVegeType.Detail covers grass and small minable rocks. So the check includes vegeProto.MiningItem.Length instead. if (vegeProto != null && vegeProto.MiningItem.Length > 0) { if ((vegeProto.Type == EVegeType.Tree && !configEnableClearingItemTree) || (vegeProto.Type == EVegeType.Stone && !configEnableClearingItemStone) || (vegeProto.Type == EVegeType.Detail && !configEnableClearingItemDetail) || (vegeProto.Type == EVegeType.Ice && !configEnableClearingItemIce)) { continue; } float distanceToVege = Vector3.Distance(___player.position, vegeData.pos); if (distanceToVege < closestVegeDistance) { bool vegeBeingProcessedFlag = false; foreach (PrebuildData prebuild in ___player.factory.prebuildPool) { if (isDroneClearingPrebuild(prebuild) && prebuild.upEntity == vegeData.id) { vegeBeingProcessedFlag = true; break; } } if (!vegeBeingProcessedFlag) { closestVegeDistance = distanceToVege; closestVegeId = vegeData.id; } } } } if (closestVegeDistance <= ___player.mecha.buildArea * configLimitClearingDistance) { VegeData vegeData = ___player.factory.vegePool[closestVegeId]; VegeProto vegeProto = LDB.veges.Select((int)vegeData.protoId); //var sb = new StringBuilder(); //sb.AppendFormat("Initiating mining of {0} to get {1} at power level {2}", vegeProto.Type.ToString(), LDB.items.Select(vegeProto.MiningItem[0]).name, ___player.mecha.coreEnergy / ___player.mecha.coreEnergyCap); //Logger.LogInfo(sb.ToString()); PrebuildData prebuild = default; prebuild.protoId = -1; prebuild.modelId = 0; // Saves always open as 0 prebuild.recipeId = -1; prebuild.refCount = 0; prebuild.upEntity = vegeData.id; prebuild.pos = prebuild.pos2 = vegeData.pos; prebuild.rot = vegeData.rot; // This operation will cause a drone to be assigned by MechaDroneLogic.UpdateTargets. int prebuildId = ___player.factory.AddPrebuildData(prebuild); UpdateTipText("(Assigning drones.)"); } else { if (configEnableDebug) { Logger.LogInfo("No enabled items within configured distance."); } UpdateTipText("(No more items in range.)"); } } }
// This function is based on PlayerAction_Mine.GameTick public void DroneGameTick() { double powerFactor = 0.01666666753590107; PlanetFactory factory = this.player.factory; if (factory == null) { // This has only been seen briefly when the Render Distance mod is transitioning to or from a planet view. return; } double miningEnergyCost = this.player.mecha.miningPower * powerFactor; double energyAvailable; float fractionOfEnergyAvailable; this.player.mecha.QueryEnergy(miningEnergyCost, out energyAvailable, out fractionOfEnergyAvailable); int miningTime = (int)(this.player.mecha.miningSpeed * configSpeedScaleFactor * fractionOfEnergyAvailable * 10000f + 0.49f); VegeData vegeData = factory.GetVegeData(this.miningId); this.miningProtoId = (int)vegeData.protoId; VegeProto vegeProto = LDB.veges.Select((int)vegeData.protoId); if (vegeProto != null) { this.miningTick += miningTime; this.player.mecha.coreEnergy -= energyAvailable; this.player.mecha.MarkEnergyChange(5, -miningEnergyCost); this.percent = Mathf.Clamp01((float)((double)this.miningTick / (double)(vegeProto.MiningTime * 10000))); if (this.miningTick >= vegeProto.MiningTime * 10000) { System.Random random = new System.Random(vegeData.id + ((this.player.planetData.seed & 16383) << 14)); bool inventoryOverflowFlag = false; int popupQueueIndex = 0; for (int itemIdx = 0; itemIdx < vegeProto.MiningItem.Length; itemIdx++) { float randomMiningChance = (float)random.NextDouble(); if (randomMiningChance < vegeProto.MiningChance[itemIdx]) { int minedItem = vegeProto.MiningItem[itemIdx]; int minedItemCount = (int)((float)vegeProto.MiningCount[itemIdx] * (vegeData.scl.y * vegeData.scl.y) + 0.5f); if (minedItemCount > 0 && LDB.items.Select(minedItem) != null) { int inventoryOverflowCount = this.player.package.AddItemStacked(minedItem, minedItemCount); if (inventoryOverflowCount != 0) { UIItemup.Up(minedItem, inventoryOverflowCount); UIRealtimeTip.PopupItemGet(minedItem, inventoryOverflowCount, vegeData.pos + vegeData.pos.normalized, popupQueueIndex++); } else // Unable to fit all items { inventoryOverflowFlag = true; } } } } VFEffectEmitter.Emit(vegeProto.MiningEffect, vegeData.pos, vegeData.rot); VFAudio.Create(vegeProto.MiningAudio, null, vegeData.pos, true); factory.RemoveVegeWithComponents(vegeData.id); GameMain.gameScenario.NotifyOnVegetableMined((int)vegeData.protoId); this.miningType = EObjectType.Entity; // This change will cause the mission to be completed. this.miningId = 0; if (inventoryOverflowFlag) { //Logger.LogInfo("Inventory overflow detected."); } this.miningTick = 0; } } else { //Logger.LogInfo("null vegeProto. Icarus likely removed clearing target."); this.miningType = EObjectType.Entity; // This change will cause the mission to be completed. this.miningId = 0; this.miningTick = 0; this.percent = 0f; factory.RemoveVegeWithComponents(vegeData.id); } }
// collision with vegetation, landing sound effect private void UpdateExtraSoundEffects(PlayerAnimationUpdate packet) { if (localPlanetId < 0) { return; } if (localPlanetId > 0) { PlanetData pData = GameMain.galaxy.PlanetById(localPlanetId); PlanetPhysics pPhys = (pData != null) ? pData.physics : null; PlanetFactory pFactory = (pData != null) ? pData.factory : null; float tmpMaxAltitude = rootTransform.localPosition.magnitude - pData.realRadius; if (tmpMaxAltitude > 1000f) { tmpMaxAltitude = 1000f; } if (rootAnimation.RunSlow.enabled || rootAnimation.RunFast.enabled || rootAnimation.Drift.enabled || rootAnimation.DriftF.enabled || rootAnimation.DriftR.enabled || rootAnimation.DriftL.enabled) { bool ground = IsGrounded(); if (DriftDetermineInWater(pData)) { if (maxAltitude > 1f && pData.waterItemId > 0) { VFAudio audio = VFAudio.Create("landing-water", base.transform, Vector3.zero, false, 0); audio.volumeMultiplier = Mathf.Clamp01(maxAltitude / 5f + 0.5f); audio.Play(); PlayFootstepEffect(true, 0f, true); PlayFootstepEffect(false, 0f, true); } maxAltitude = 0f; } if (ground && maxAltitude > 3f) { VFAudio audio = VFAudio.Create("landing", base.transform, Vector3.zero, false, 0); audio.volumeMultiplier = Mathf.Clamp01(maxAltitude / 25f + 0.5f); audio.Play(); maxAltitude = 0f; } if (!ground && tmpMaxAltitude > maxAltitude) { maxAltitude = tmpMaxAltitude; } } else { maxAltitude = 15f; } // NOTE: the pPhys can only be loaded if the player trying to load it has the planet actually loaded (meaning he is on the same planet or near it) if (pPhys != null && pFactory != null && packet.horzSpeed > 5f) { int number = Physics.OverlapSphereNonAlloc(base.transform.localPosition, 1.8f, collider, 1024, QueryTriggerInteraction.Collide); for (int i = 0; i < number; i++) { int colId = pPhys.nearColliderLogic.FindColliderId(collider[i]); ColliderData cData = pPhys.GetColliderData(colId); if (cData.objType == EObjectType.Vegetable && cData.objId > 0) { VegeData vData = pFactory.vegePool[cData.objId]; VegeProto vProto = LDB.veges.Select((int)vData.protoId); if (vProto != null && vProto.CollideAudio > 0 && vegeCollideColdTime <= 0) { VFAudio.Create(vProto.CollideAudio, base.transform, Vector3.zero, true, 0); vegeCollideColdTime = UnityEngine.Random.value * 0.23f + 0.1f; } } } } } if (vegeCollideColdTime > 0) { vegeCollideColdTime -= Time.deltaTime * 2; } else { vegeCollideColdTime = 0; } }