示例#1
0
        // return resource cache for a vessel
        public static Vessel_resources Get(Vessel v)
        {
            // try to get existing entry if any
            Vessel_resources entry;

            if (entries.TryGetValue(v.id, out entry))
            {
                return(entry);
            }

            // create new entry
            entry = new Vessel_resources();

            // remember new entry
            entries.Add(v.id, entry);

            // return new entry
            return(entry);
        }
示例#2
0
        // execute the recipe
        public bool Execute(Vessel v, Vessel_resources resources)
        {
            // determine worst input ratio
            // - pure input recipes can just underflow
            double worst_input = left;

            if (outputs.Count > 0)
            {
                for (int i = 0; i < inputs.Count; ++i)
                {
                    Entry e = inputs[i];
                    Resource_info_view res = GetResourceInfoView(v, resources, e.name);
                    // handle combined inputs
                    if (e.combined != null)
                    {
                        // is combined resource the primary
                        if (e.combined != "")
                        {
                            Entry sec_e                  = inputs.Find(x => x.name.Contains(e.combined));
                            Resource_info_view sec       = GetResourceInfoView(v, resources, sec_e.name);
                            double             pri_worst = Lib.Clamp((res.amount + res.deferred) * e.inv_quantity, 0.0, worst_input);
                            if (pri_worst > 0.0)
                            {
                                worst_input = pri_worst;
                            }
                            else
                            {
                                worst_input = Lib.Clamp((sec.amount + sec.deferred) * sec_e.inv_quantity, 0.0, worst_input);
                            }
                        }
                    }
                    else
                    {
                        worst_input = Lib.Clamp((res.amount + res.deferred) * e.inv_quantity, 0.0, worst_input);
                    }
                }
            }

            // determine worst output ratio
            // - pure output recipes can just overflow
            double worst_output = left;

            if (inputs.Count > 0)
            {
                for (int i = 0; i < outputs.Count; ++i)
                {
                    Entry e = outputs[i];
                    if (!e.dump)                     // ignore outputs that can dump overboard
                    {
                        Resource_info_view res = GetResourceInfoView(v, resources, e.name);
                        worst_output = Lib.Clamp((res.capacity - (res.amount + res.deferred)) * e.inv_quantity, 0.0, worst_output);
                    }
                }
            }

            // determine worst-io
            double worst_io = Math.Min(worst_input, worst_output);

            // consume inputs
            for (int i = 0; i < inputs.Count; ++i)
            {
                Entry e = inputs[i];
                Resource_info_view res = GetResourceInfoView(v, resources, e.name);
                // handle combined inputs
                if (e.combined != null)
                {
                    // is combined resource the primary
                    if (e.combined != "")
                    {
                        Entry sec_e             = inputs.Find(x => x.name.Contains(e.combined));
                        Resource_info_view sec  = GetResourceInfoView(v, resources, sec_e.name);
                        double             need = (e.quantity * worst_io) + (sec_e.quantity * worst_io);
                        // do we have enough primary to satisfy needs, if so don't consume secondary
                        if (res.amount + res.deferred >= need)
                        {
                            resources.Consume(v, e.name, need, name);
                        }
                        // consume primary if any available and secondary
                        else
                        {
                            need -= res.amount + res.deferred;
                            res.Consume(res.amount + res.deferred, name);
                            sec.Consume(need, name);
                        }
                    }
                }
                else
                {
                    res.Consume(e.quantity * worst_io, name);
                }
            }

            // produce outputs
            for (int i = 0; i < outputs.Count; ++i)
            {
                Entry e = outputs[i];
                Resource_info_view res = GetResourceInfoView(v, resources, e.name);
                res.Produce(e.quantity * worst_io, name);
            }

            // produce cures
            for (int i = 0; i < cures.Count; ++i)
            {
                Entry           entry       = cures[i];
                List <RuleData> curingRules = new List <RuleData>();
                foreach (ProtoCrewMember crew in v.GetVesselCrew())
                {
                    KerbalData kd = DB.Kerbal(crew.name);
                    if (kd.sickbay.IndexOf(entry.combined + ",", StringComparison.Ordinal) >= 0)
                    {
                        curingRules.Add(kd.Rule(entry.name));
                    }
                }

                foreach (RuleData rd in curingRules)
                {
                    rd.problem -= entry.quantity * worst_io / curingRules.Count;
                    rd.problem  = Math.Max(rd.problem, 0);
                }
            }

            // update amount left to execute
            left -= worst_io;

            // the recipe was executed, at least partially
            return(worst_io > double.Epsilon);
        }
示例#3
0
 private Resource_info_view GetResourceInfoView(Vessel v, Vessel_resources resources, string resource_name)
 {
     return(resources.Info(v, resource_name).GetResourceInfoView());
 }