diff --git a/src/sgame/components/MiningComponent.cpp b/src/sgame/components/MiningComponent.cpp index fe3de7f1db0..fcc9ee80b18 100644 --- a/src/sgame/components/MiningComponent.cpp +++ b/src/sgame/components/MiningComponent.cpp @@ -11,6 +11,8 @@ MiningComponent::MiningComponent(Entity& entity, bool blueprint, // Inform neighbouring miners so they can adjust their own predictions. // Note that blueprint miners skip this. InformNeighbors(); + + REGISTER_THINKER(Think, ThinkingComponent::SCHEDULER_AVERAGE, 250); } void MiningComponent::HandlePrepareNetCode() { @@ -47,7 +49,25 @@ void MiningComponent::HandleDie(gentity_t* /*killer*/, meansOfDeath_t /*meansOfD G_UpdateBuildPointBudgets(); } -float MiningComponent::InterferenceMod(float distance) { +float MiningComponent::AliveTimePercentage() const { + constexpr float fullyActiveTime = 3.0f * 60.0f * 1000.0f; // 3 minutes + + Log::Warn("creation time: %i", entity.oldEnt->creationTime); + if (entity.oldEnt->creationTime < 1000) + return 1.0f; // spawned with world, can be considered alive since long + + // TODO: use time after activating, and not after spawning + float activeTime = static_cast( + level.time - entity.oldEnt->creationTime); + + return Math::Clamp(activeTime / fullyActiveTime, 0.0f, 1.0f); +} + +float MiningComponent::AliveTimeMod() const { + return AliveTimePercentage(); +} + +float MiningComponent::PredictedInterferenceMod(float distance) { if (RGS_RANGE <= 0.0f) return 1.0f; if (distance > 2.0f * RGS_RANGE) return 1.0f; @@ -76,7 +96,7 @@ void MiningComponent::CalculateEfficiency() { HealthComponent *healthComponent = other.Get(); if (healthComponent && !healthComponent->Alive()) return; - float interferenceMod = InterferenceMod(G_Distance(entity.oldEnt, other.oldEnt)); + float interferenceMod = PredictedInterferenceMod(G_Distance(entity.oldEnt, other.oldEnt)); // TODO: Exclude enemy miners in construction from the prediction. @@ -89,6 +109,7 @@ void MiningComponent::CalculateEfficiency() { if (!miningComponent.Active()) return; currentEfficiency *= interferenceMod; + currentEfficiency *= AliveTimeMod(); }); } @@ -108,3 +129,19 @@ void MiningComponent::InformNeighbors() { float MiningComponent::Efficiency(bool predict) { return predict ? predictedEfficiency : currentEfficiency; } + +void MiningComponent::Think(int) +{ + // Already calculate the predicted efficiency. + CalculateEfficiency(); + + // Inform neighbouring miners so they can adjust their own predictions. + // Note that blueprint miners skip this. + InformNeighbors(); + + // Update both team's budgets. + G_UpdateBuildPointBudgets(); + + // TODO: stop thinking after some time + //GetThinkingComponent().UnregisterActiveThinker(); +} diff --git a/src/sgame/components/MiningComponent.h b/src/sgame/components/MiningComponent.h index 30e0fc7cdf1..9dd2d1a4bca 100644 --- a/src/sgame/components/MiningComponent.h +++ b/src/sgame/components/MiningComponent.h @@ -17,7 +17,8 @@ class MiningComponent: public MiningComponentBase { * @param r_ThinkingComponent A ThinkingComponent instance that this component depends on. * @note This method is an interface for autogenerated code, do not modify its signature. */ - MiningComponent(Entity& entity, bool blueprint, ThinkingComponent& r_ThinkingComponent); + MiningComponent(Entity& entity, bool blueprint, + ThinkingComponent& r_ThinkingComponent); /** * @brief Handle the PrepareNetCode message. @@ -45,7 +46,7 @@ class MiningComponent: public MiningComponentBase { * @brief Calculates modifier for the efficiency of one miner when another one interferes at * given distance. */ - static float InterferenceMod(float distance); + static float PredictedInterferenceMod(float distance); /** * @return Whether the miner is currently mining (and interfering with other miners). @@ -70,6 +71,8 @@ class MiningComponent: public MiningComponentBase { int Budget(bool predict = false); private: + void Think(int timeDelta); + /** * @brief Whether the miner is currently mining (and interfering with other miners). */ @@ -94,6 +97,18 @@ class MiningComponent: public MiningComponentBase { * @brief Adjust the rate of all other mining structures in range. */ void InformNeighbors(); + + /** + * @brief The percentage of time elasped before the drill + * works at full capacity + */ + float AliveTimePercentage() const; + + /** + * @brief Calculates modifier for the efficiency of a miner + * given how long it lived. + */ + float AliveTimeMod() const; }; #endif // MINING_COMPONENT_H_ diff --git a/src/sgame/sg_buildpoints.cpp b/src/sgame/sg_buildpoints.cpp index b0f2cb6953e..52ad732bfc1 100644 --- a/src/sgame/sg_buildpoints.cpp +++ b/src/sgame/sg_buildpoints.cpp @@ -52,7 +52,7 @@ float G_RGSPredictOwnEfficiency(vec3_t origin) { static float RGSPredictEfficiencyLoss(Entity& miner, vec3_t newMinerOrigin) { float distance = Distance(miner.oldEnt->s.origin, newMinerOrigin); float oldPredictedEfficiency = miner.Get()->Efficiency(true); - float newPredictedEfficiency = oldPredictedEfficiency * MiningComponent::InterferenceMod(distance); + float newPredictedEfficiency = oldPredictedEfficiency * MiningComponent::PredictedInterferenceMod(distance); float efficiencyLoss = newPredictedEfficiency - oldPredictedEfficiency; buildpointLogger.Debug("Predicted efficiency loss of existing miner: %f - %f = %f.",