I was wondering why crop diseases spreading from one field to the next didn’t seem all that important in practice, and I think I’ve worked out why. It simply doesn’t happen at all. There are, I believe, two bugs (at least) in the code that’s supposed to make this happen. I can’t hard confirm it without dev tools, but looking into the runtime memory and running some experiments seems to confirm it.
At the end of the farming year (aka, a few days into winter, when any unharvested crops are removed), the following method gets called on the CropDiseaseTrait
of each Cropfield
.
private void SpreadDiseases()
{
// ...
foreach (CropDisease cropDisease in this.diseases)
{
float rand = Mathf.Clamp01(UnityEngine.Random.Range(0f, 1f) * this.GetCropDiseaseChanceMult());
if (rand > 0f && cropDisease.chanceToSpread <= rand)
{
foreach (Cropfield cropfield in base.resourceManager.cropFieldsRO)
{
if (cropfield != this.field && Vector3.Distance(this.field.transform.position, cropfield.transform.position) <= cropDisease.spreadDistance)
{
// ...
ICropfieldScheduledItem currentItem = cropfield.cropScheduler.currentScheduledItem;
if (currentItem != null && currentItem is CropfieldPlantingScheduledItem)
{
if ((currentItem as CropfieldPlantingScheduledItem).recordName == cropDisease.recordName)
{
cropfield.Infect(cropDisease.recordName);
break;
}
break;
}
}
}
}
}
}
(where I’ve tidied up and removed the unimportant parts of the decompiled code).
There are two things that prevent cropfield.Infect
from being called. Firstly, because this method is called in winter cropScheduler.currentScheduledItem
is always null (because there’s no farming happening at that time). Secondly, it’s comparing the recordName
of a CropfieldPlantingScheduledItem
with that of a CropDisease
. But those are very different. The former is something like PeaField while the latter are of the form CropDisease_StemRot, so that last equallity check will also fail. I’m guessing it’s meant to check that the crop being grown is susceptible to the disease being spread, but it’s not doing that.
I tried manually calling this method over and over again on an infected field, and the disease never spread, which seems to confirm my suspicions. This is all about diseases spreading however, disease do spontaneously appear on crops when they sown as presumably intended.
I’d also add that, even if the name check is solved and some cropScheduler.nextScheduledItem
is implemented, having diseases spreading between fields over winter would be problematic. Firstly, it means that spreading only matters to crops at the start of the year and would discourage having offset crop rotations and actually encourage having the same crops growing at the same time in different fields. Secondly, it would be very exploitable in an incredibly tedious way: manually deleting crop rotations over winter so there’s no target for spreading, before recreating them in spring. IMO, having diseases spread when crops mature (just before rolling for new diseases) would make a lot more sense to me. Or, even simpler, increase the odds of rolling a new disease for every field in range where it is already present.