Checking if a hopper has X resourses.

Started by Timber, November 01, 2014, 10:09:43 PM

Previous topic - Next topic

Timber

Hello,

I'm trying to make a building consume resources from a nearby hopper. I plan to butcher some of the nutrient dispenser code for this, specifically:


public Thing DispenseFood()
{
if (!this.CanDispenseNow)
{
return null;
}
int num = this.def.building.foodCostPerDispense;
if (Find.ResearchManager.IsFinished(ResearchProjectDef.Named("NutrientResynthesis")))
{
num--;
}
int num2 = 0;
List<ThingDef> list = new List<ThingDef>();
Thing foodInHopper = this.FoodInHopper;
do
{
int num3 = Mathf.Min(foodInHopper.stackCount, num);
num2 += num3;
list.Add(foodInHopper.def);
foodInHopper.SplitOff(num3);
if (num2 >= num)
{
break;
}
foodInHopper = this.FoodInHopper;
}
while (foodInHopper != null);
this.def.building.soundDispense.PlayOneShot(base.Position);
Meal meal = (Meal)ThingMaker.MakeThing(ThingDef.Named("MealNutrientPaste"), null);
foreach (ThingDef current in list)
{
meal.RegisterIngredient(current);
}
return meal;
}
while (foodInHopper != null);
this.def.building.soundDispense.PlayOneShot(base.Position);
Meal meal = (Meal)ThingMaker.MakeThing(ThingDef.Named("MealNutrientPaste"), null);
foreach (ThingDef current in list)
{
meal.RegisterIngredient(current);
}
return meal;

I'm just starting to learn C# (coming from Java) so I don't understand everything fully. Could someone walk me through what this bit does?


do
{
int num3 = Mathf.Min(foodInHopper.stackCount, num);
num2 += num3;
list.Add(foodInHopper.def);
foodInHopper.SplitOff(num3);
if (num2 >= num)
{
break;
}
foodInHopper = this.FoodInHopper;
}


Which will obviously require a method to check if there is food:


private Thing FoodInHopper
{
get
{
ThingDef thingDef = ThingDef.Named("Hopper");
foreach (IntVec3 current in GenAdj.AdjacentSquaresCardinal(this))
{
Thing thing = null;
Thing thing2 = null;
foreach (Thing current2 in Find.ThingGrid.ThingsAt(current))
{
if (current2.def.IsFood)
{
thing = current2;
}
if (current2.def == thingDef)
{
thing2 = current2;
}
}
if (thing != null && thing2 != null)
{
return thing;
}
}
return null;
}
}


My question is: how do I make the method look for specific resources like wood or cloth instead of food?
I ask not for a lighter burden but for broader shoulders. -Atlas

Rikiki

Hi!
This is a "do { treatment } while condition" instruction.
It will perform the treatment at least once and repeat it until condition becomes true.
This piece of code is getting the avaible food in nearby hoppers:
- int num3 = Mathf.Min(foodInHopper.stackCount, num); // get just the required amount of food or all the stack if there is not enough.
- num2 += num3; // Increment the total available quantity of food.
- list.Add(foodInHopper.def); // Will be used to determine the meal content.
- foodInHopper.SplitOff(num3); // Remove num3 food from the current hopper.
- if (num2 >= num) // If the require amount of food is available, breaks the "do while" loop.

Warning! The trick you have to understand here is that each time "foodInHopper" is read, the corresponding
private Thing FoodInHopper
{
get
{

function is called!
I hope I am clear, this peace of code is not easy to understand... :P

For the specific content, replace this:
if (current2.def.IsFood)
by this:
if (current2.def.defName == "YourResourceDefName")

I believe there are mods which already perform this kind of treatment (Industrial Rim or TTM grill??).

Timber

#2
I know what you mean about the function being called for each interaction - it makes sense if you think about what the dispenser does: produce a meal every time a colonist interacts with it.

I think I should be able to butcher it for my ticker. Thanks for the help!
I ask not for a lighter burden but for broader shoulders. -Atlas