Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - desert

#1
Mods / Re: [Mod Request] Enhanced Trade Beacon
July 20, 2017, 05:02:11 AM
GOOD NEWS: A WORKAROUND

PeteTimeSix's QoL Tweaks Pack allows any stockpile to be set as a trading stockpile. Any such designated stockpile will contribute items to orbital trading.

It's not a direct adjustment to trading or structures, but it accomplishes what I want without otherwise interfering (other mod features may be disabled if one wishes).
#2
Mods / Re: [Mod Request] Enhanced Trade Beacon
July 19, 2017, 07:39:42 PM
Quote from: Sion on July 19, 2017, 04:50:08 PM
Do you want to sell everything everywhere that lies on the map, or only things in your stockpiles?

I think it's better to skip the checks all together and just return a list of all items or your stockpiles only, because I think the game are already tracking those so there are no need to search for them again.

I believe the sample code provided in OP will identify every cell on the map as a "tradeable cell", so any valid item in any cell will be listed as tradeable. That is, in the function TradeableCellsAround, the base game checks are replaced with

return map.AllCells.ToList()
#3
Mods / [Mod Request] Enhanced Trade Beacon
July 18, 2017, 12:26:37 PM
A trade beacon with full-map radius. Accomplished by either creating a new beacon-like structure with a larger radius, or modding the original beacon. Likely involves C#.

For example:

Replace the TradeableCellsAround function in the object Building_OrbitalTradeBeacon with code enabling full-map coverage for the trade beacon.
public static List<IntVec3> TradeableCellsAround(IntVec3 pos, Map map)
{
Building_OrbitalTradeBeacon.tradeableCells.Clear();
if (!pos.InBounds(map))
{
return Building_OrbitalTradeBeacon.tradeableCells;
}
return map.AllCells.ToList();
}


Supplementary edit to the structure XML removing the building radius highlight. In the Core mod Thingsdef_Buildings file "Buildings_Misc.xml", the code enabling radius highlight seems to be:
<placeWorkers>
      <li>PlaceWorker_ShowTradeBeaconRadius</li>
    </placeWorkers>


Reference to this thread.
#4
Outdated / Re: [A16-A17] BaconBits' Mods ~ 06/28/17
July 11, 2017, 09:00:32 PM
Did they not in the past? If they take up a space, at least for my play they are not a useful alternative to the standing lamp once its power usage is adjusted.
#5
Outdated / Re: [A16-A17] BaconBits' Mods ~ 06/28/17
July 11, 2017, 04:42:00 PM
Are the wall torches meant to block an entire square? The images in the main post suggest that squares with wall torches are still passable to pawns and zoneable for items.
#6
Mods / Re: [Mod Idea] Re: Trade Beacon Limitations
July 09, 2017, 03:56:05 PM
Any thoughts? Here are the options as determined:

1.  Replace the TradeableCellsAround function in the object(?) Building_OrbitalTradeBeacon with code enabling full-map coverage for the trade beacon. Supplementary edit to the structure XML removing the building radius highlight.
public static List<IntVec3> TradeableCellsAround(IntVec3 pos, Map map)
{
Building_OrbitalTradeBeacon.tradeableCells.Clear();
if (!pos.InBounds(map))
{
return Building_OrbitalTradeBeacon.tradeableCells;
}
return map.AllCells.ToList();
}

2. To avoid having to mod the source code, create a simpler mod that duplicates the Orbital Trade Beacon with above changed functionality, but as a distinct construction from the base-game OTB.
#7
The thread title poses a more general question, but my immediate interest is in getting colonists to eat single servings of insect jelly.

Insect jelly gives a mood buff, so that's nice, but I don't want colonists to demolish my inventory for full meals.

Morsels, eh?
#8
Quote from: MajorMonotone on July 07, 2017, 04:31:35 AM
Quote from: jamaicancastle on July 07, 2017, 03:37:45 AM
The problem with being able to become friendly with the hostile factions is, eventually there'd be no one left to raid you, and then what would Randy do when he hates your guts?
Well by the time that we get to having diplomacy this in depth I imagine there'll be more in depth faction mechanics to help differentiate our selves from the other inhabitants. Possibly a government arch type or religion that encourages cooperation or hostility with other types of governments or religions. It'd be interesting to see a faction not be happy with how you treat your colonists and then possibly trying to coerce them to leave your faction and join theirs. Conditions could be different depending on their government or religion type, for example a communist faction could be unhappy with you that your colonists did not all have the same living standards or that you were exploiting other people for profit.

Is it? A dynamic world civilization would hold plenty of individuals, groups, and subgroups to target you at one time or another. As it is though these planets only harbor a few thousand human inhabitants (fewer than may visit/attack you over the years?), so all these questions need to be taken as part of a comprehensive social overhaul.

For instance, why at any given time can't your band of colonists cut their losses and run for the cities? "Park Rescue Service, we tried setting up a compound in the wilderness and we can't make it anymore!"
#9
Mods / Re: [Mod Idea] Re: Trade Beacon Limitations
July 07, 2017, 07:05:21 AM
Quote from: jamaicancastle on July 07, 2017, 03:28:31 AM
So I tracked down the code that NPC travelers/caravans appear to use for their trading, which is in the Pawn_TraderTracker class. For reasons totally inexplicable to me, it has a completely different structure to it that I don't think can be neatly fitted into the orbital trade ship code. So let's look at the beacon:

The relevant function there, as you can probably guess, is TradeableCellsAround. As you noted, it seems to have hardcoded the 7.9f value for its radius rather than actually referring to the constant, in a way guaranteed to annoy your CS professor. (Probably an oversight.) The only one that actually does anything is the one in the function; the constant, as far as I can tell, isn't actually referred to anywhere.

Anyway, you can modify that to turn it up to 50 or 100 or 1,000 or whatever else you want (just remember that it expects a float: "100f"), but as I mentioned above, that's not the whole story.

RegionTraverser.BreadthFirstTraverse(region, [some other unimportant parameters], 13, RegionType.Set_Passable);
This is part of the TradeableCellsAround function; it's the bit that, after checking for various error cases, actually populates the list of cells. (One of the parts I elided is where the 7.9f radius is established, incidentally, in a very inside-out bit of code that makes my head ache.) In this case is uses regions, which are bits of the map that the game uses to build things like rooms, temperature variations, and whatnot. The key point is the RegionType.Set_Passable. This means it will only attempt to crawl regions that are fully passable (not walls or doors) in order to find what it's looking for. The 13, incidentally, is related to the depth with which it will search, although in a way that's not totally clear to me. (Hey, I didn't take Algorithms as an undergrad. Maybe should've.)

So basically, you would have the following options:
- Just change the 7.9f in TradeableCellsAround to another value, say 100.0f. It would still be blocked by doors, but you could put one outside and have all the storage space you could practically need (it doesn't care about roofs, so put up a roofed but unwalled space off to one side for perishables). In practice, depending on how Rimworld sets up regions, you might or might not need to experiment with replacing the 13 above it with a higher number.
- You could change the beacon to search impassable as well as passable terrain with a huge radius, but there's really not much point, because you're better off with this:
- Cut right to the chase and just give it all the cells in the map. Delete everything after the first "if" block to the end of the function, and replace it with:
return map.AllCells.ToList();

There is one caveat with this method: I have no idea how much lag it will produce. I assume some. This would manifest at three times: when placing an OTB*, when one is first built, and when a trade ship actually arrives (it shouldn't-but-might also show up when you sell item(s)). Also, absolutely don't touch the "create stockpile" button with an OTB with this mod; it'll try to make your entire map into a stockpile with, I imagine, hilarious results.

* You might or might not be able to solve this by removing the placeWorkers block from the OTB's XML. This will stop it trying to show the radius of the OTB while placing (or selecting) it, which is just as well since obviously it's just going to highlight the whole map.

Unfortunately, when it comes to actually putting these insights into practice with a mod, I am something of a beginner as well, so I would be grateful if one of our other regulars could explain that bit? (That is, given specific changes that have to happen to this one existing function, what's the best way to patch it?)

Excellent work. So, toward a workable mod that sets a beacon to consider the whole map*, we have three elements:

1. Replace the TradeableCellsAround function in the object(?) Building_OrbitalTradeBeacon with code enabling full-map coverage for the trade beacon.
public static List<IntVec3> TradeableCellsAround(IntVec3 pos, Map map)
{
Building_OrbitalTradeBeacon.tradeableCells.Clear();
if (!pos.InBounds(map))
{
return Building_OrbitalTradeBeacon.tradeableCells;
}
return map.AllCells.ToList();
}


2. Supplementary edit to the structure XML removing the building radius highlight.
3. What is the actual mod to be implemented? The original source code is being overridden, so how does that proceed?

Would it be technically simpler to duplicate the OTB, create a new structure that duplicates the functions, but with the desired changes? Call it OTB 2.0...

*I imagine with this proposed mod you would never need more than one beacon, but would building more than one with the new functionality create interference or other problems?
#10
Mods / Re: [Mod Idea] Re: Trade Beacon Limitations
July 06, 2017, 11:46:57 PM
Quote from: jamaicancastle on July 06, 2017, 04:04:38 PM
Just changing that variable won't be enough, because orbital trade beacons obey walls and doors, so it wouldn't be able to find things in buildings. However, if you're willing to make a C# mod, you should be able to find the part of the trading code where it collects items from the trade beacon, and simply tell it to use the ground trader item-finding code instead.

Well alright, but I would need someone's help with this, given my code illiteracy.

Using the recommended decompiler ILSpy, I find the item (?) TradeUtility, which contains all the following code:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Verse;
using Verse.AI.Group;

namespace RimWorld
{
public static class TradeUtility
{
public static bool EverTradeable(ThingDef def)
{
return def.tradeability != Tradeability.Never && ((def.category == ThingCategory.Item || def.category == ThingCategory.Pawn) && def.GetStatValueAbstract(StatDefOf.MarketValue, null) > 0f);
}

public static void SpawnDropPod(IntVec3 dropSpot, Map map, Thing t)
{
DropPodUtility.MakeDropPodAt(dropSpot, map, new ActiveDropPodInfo
{
SingleContainedThing = t,
leaveSlag = false
});
}

[DebuggerHidden]
public static IEnumerable<Thing> AllLaunchableThings(Map map)
{
HashSet<Thing> yieldedThings = new HashSet<Thing>();
foreach (Building_OrbitalTradeBeacon beacon in Building_OrbitalTradeBeacon.AllPowered(map))
{
foreach (IntVec3 c in beacon.TradeableCells)
{
List<Thing> thingList = c.GetThingList(map);
for (int i = 0; i < thingList.Count; i++)
{
Thing t = thingList[i];
if (TradeUtility.EverTradeable(t.def) && t.def.category == ThingCategory.Item && !yieldedThings.Contains(t) && TradeUtility.TradeableNow(t))
{
yieldedThings.Add(t);
yield return t;
}
}
}
}
}

[DebuggerHidden]
public static IEnumerable<Pawn> AllSellableColonyPawns(Map map)
{
foreach (Pawn p in map.mapPawns.PrisonersOfColonySpawned)
{
if (p.guest.PrisonerIsSecure)
{
yield return p;
}
}
foreach (Pawn p2 in map.mapPawns.SpawnedPawnsInFaction(Faction.OfPlayer))
{
if (p2.RaceProps.Animal && p2.HostFaction == null && !p2.InMentalState && !p2.Downed && map.mapTemperature.SeasonAndOutdoorTemperatureAcceptableFor(p2.def))
{
yield return p2;
}
}
}

public static Thing ThingFromStockToMergeWith(ITrader trader, Thing thing)
{
if (thing is Pawn)
{
return null;
}
foreach (Thing current in trader.Goods)
{
if (TransferableUtility.TransferAsOne(current, thing))
{
return current;
}
}
return null;
}

public static bool TradeableNow(Thing t)
{
return !t.IsNotFresh();
}

public static void LaunchThingsOfType(ThingDef resDef, int debt, Map map, TradeShip trader)
{
while (debt > 0)
{
Thing thing = null;
foreach (Building_OrbitalTradeBeacon current in Building_OrbitalTradeBeacon.AllPowered(map))
{
foreach (IntVec3 current2 in current.TradeableCells)
{
foreach (Thing current3 in map.thingGrid.ThingsAt(current2))
{
if (current3.def == resDef)
{
thing = current3;
goto IL_C6;
}
}
}
}
IL_C6:
if (thing == null)
{
Log.Error("Could not find any " + resDef + " to transfer to trader.");
break;
}
int num = Math.Min(debt, thing.stackCount);
if (trader != null)
{
trader.GiveSoldThingToTrader(thing, num, TradeSession.playerNegotiator);
}
else
{
thing.SplitOff(num).Destroy(DestroyMode.Vanish);
}
debt -= num;
}
}

public static void LaunchSilver(Map map, int fee)
{
TradeUtility.LaunchThingsOfType(ThingDefOf.Silver, fee, map, null);
}

public static Map PlayerHomeMapWithMostLaunchableSilver()
{
return (from x in Find.Maps
where x.IsPlayerHome
select x).MaxBy((Map x) => (from t in TradeUtility.AllLaunchableThings(x)
where t.def == ThingDefOf.Silver
select t).Sum((Thing t) => t.stackCount));
}

public static bool ColonyHasEnoughSilver(Map map, int fee)
{
return (from t in TradeUtility.AllLaunchableThings(map)
where t.def == ThingDefOf.Silver
select t).Sum((Thing t) => t.stackCount) >= fee;
}

public static void CheckInteractWithTradersTeachOpportunity(Pawn pawn)
{
if (pawn.Dead)
{
return;
}
Lord lord = pawn.GetLord();
if (lord != null && lord.CurLordToil is LordToil_DefendTraderCaravan)
{
LessonAutoActivator.TeachOpportunity(ConceptDefOf.InteractingWithTraders, pawn, OpportunityType.Important);
}
}
}
}



This element seems to enumerate things to trade for the UI if they are within the specified range of of the beacons.

public static IEnumerable<Thing> AllLaunchableThings(Map map)
{
HashSet<Thing> yieldedThings = new HashSet<Thing>();
foreach (Building_OrbitalTradeBeacon beacon in Building_OrbitalTradeBeacon.AllPowered(map))
{
foreach (IntVec3 c in beacon.TradeableCells)
{
List<Thing> thingList = c.GetThingList(map);
for (int i = 0; i < thingList.Count; i++)
{
Thing t = thingList[i];
if (TradeUtility.EverTradeable(t.def) && t.def.category == ThingCategory.Item && !yieldedThings.Contains(t) && TradeUtility.TradeableNow(t))
{
yieldedThings.Add(t);
yield return t;
}
}
}
}
}


I don't know how to find the code for caravan/land trade. What would I do here?

Alternatively, the item Building_Orbital Trade Beacon contains the code Cryusaki posted; the "7.9f" figure appears twice. How would I safely change the effective radius here if that were the plan?

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using UnityEngine;
using Verse;

namespace RimWorld
{
public class Building_OrbitalTradeBeacon : Building
{
private const float TradeRadius = 7.9f;

private static List<IntVec3> tradeableCells = new List<IntVec3>();

public IEnumerable<IntVec3> TradeableCells
{
get
{
return Building_OrbitalTradeBeacon.TradeableCellsAround(base.Position, base.Map);
}
}

[DebuggerHidden]
public override IEnumerable<Gizmo> GetGizmos()
{
foreach (Gizmo g in base.GetGizmos())
{
yield return g;
}
if (DesignatorUtility.FindAllowedDesignator<Designator_ZoneAddStockpile_Resources>() != null)
{
yield return new Command_Action
{
action = new Action(this.MakeMatchingStockpile),
hotKey = KeyBindingDefOf.Misc1,
defaultDesc = "CommandMakeBeaconStockpileDesc".Translate(),
icon = ContentFinder<Texture2D>.Get("UI/Designators/ZoneCreate_Stockpile", true),
defaultLabel = "CommandMakeBeaconStockpileLabel".Translate()
};
}
}

private void MakeMatchingStockpile()
{
Designator des = DesignatorUtility.FindAllowedDesignator<Designator_ZoneAddStockpile_Resources>();
des.DesignateMultiCell(from c in this.TradeableCells
where des.CanDesignateCell(c).Accepted
select c);
}

public static List<IntVec3> TradeableCellsAround(IntVec3 pos, Map map)
{
Building_OrbitalTradeBeacon.tradeableCells.Clear();
if (!pos.InBounds(map))
{
return Building_OrbitalTradeBeacon.tradeableCells;
}
Region region = pos.GetRegion(map, RegionType.Set_Passable);
if (region == null)
{
return Building_OrbitalTradeBeacon.tradeableCells;
}
RegionTraverser.BreadthFirstTraverse(region, (Region from, Region r) => r.portal == null, delegate(Region r)
{
foreach (IntVec3 current in r.Cells)
{
if (current.InHorDistOf(pos, 7.9f))
{
Building_OrbitalTradeBeacon.tradeableCells.Add(current);
}
}
return false;
}, 13, RegionType.Set_Passable);
return Building_OrbitalTradeBeacon.tradeableCells;
}

[DebuggerHidden]
public static IEnumerable<Building_OrbitalTradeBeacon> AllPowered(Map map)
{
foreach (Building_OrbitalTradeBeacon b in map.listerBuildings.AllBuildingsColonistOfClass<Building_OrbitalTradeBeacon>())
{
CompPowerTrader power = b.GetComp<CompPowerTrader>();
if (power == null || power.PowerOn)
{
yield return b;
}
}
}
}
}

#11
Mods / [Mod Idea] Re: Trade Beacon Limitations
July 06, 2017, 09:56:32 AM
What could be done to allow full-map trade through a beacon or console, like with land-agent trade?

At the very least, for the existing beacon framework where would I go to change the beacon stockpile radius?
#12
Ideas / Trade Beacon (Full) Map Coverage
June 30, 2017, 01:00:29 AM
Why does the beacon delimit a space in which trade items are detected? Besides the fundamental sense that it should just have full coverage in the first place, a limited beacon requires the player to further wrestle with the game's extremely finicky stockpile system. Having direct trade through the comm console with full map coverage (just as with personal trade on the ground) would save the player time and effort as a matter of quality of life.

Speaking of which, I would be grateful to know of any existing mods that implement this or something like it, or information on how to implement it for myself.
#13
About Extended Storage: For Apparel (Clothing Rack), how can you access all the items below the first one?

Also, there seems to be a bug with the Steel Skip furniture, namely that it deletes all but one standard stack of its contents upon reload. For example, below a skip with 563 limestone blocks resets to one stack of 75 upon load.


Loading game from file New Arrivals 4 with mods Core, HugsLib, P-Music, EdBPrepareCarefully, FollowMe, MadSkills-A17-2.0.1, HelpTab, MedicalTab, Notifications Archiver, AllowDeadMansApparel, AllowTool, ExtendedStorage-ExtendedStorage2.1, StackMerger, RW_RefugeeStats, Grenade Fix Rearmed, ReclaimFabric-ReclaimFabric1.9, ResearchPal, Efficient Light-A17, and Hand Me That Brick
Verse.Log:Message(String)
Verse.SavedGameLoader:LoadGameFromSaveFile(String)
Verse.Root_Play:<Start>m__84F()
Verse.LongEventHandler:RunEventFromAnotherThread(Action)
Verse.LongEventHandler:<UpdateCurrentAsynchronousEvent>m__84C()

Spawned BlocksLimestone493437 with stackCount 563 but stackLimit is 75. Truncating.
Verse.Log:Error(String)
Verse.Thing:SpawnSetup_Patch0(Object, Map, Boolean)
Verse.ThingWithComps:SpawnSetup(Map, Boolean)
Verse.GenSpawn:Spawn(Thing, IntVec3, Map, Rot4, Boolean)
Verse.Map:FinalizeLoading()
Verse.Game:LoadGame()
Verse.SavedGameLoader:LoadGameFromSaveFile(String)
Verse.Root_Play:<Start>m__84F()
Verse.LongEventHandler:RunEventFromAnotherThread(Action)
Verse.LongEventHandler:<UpdateCurrentAsynchronousEvent>m__84C()

GrenadeFixRearmed :: Added minRange for 0 explosive verbs.
Verse.Log:Message(String)
GrenadeFixRearmed.GrenadeFixRearmed:InjectDefs()
GrenadeFixRearmed.GrenadeFixRearmed:LoadedGame()
Verse.GameComponentUtility:LoadedGame()
Verse.Game:LoadGame()
Verse.SavedGameLoader:LoadGameFromSaveFile(String)
Verse.Root_Play:<Start>m__84F()
Verse.LongEventHandler:RunEventFromAnotherThread(Action)
Verse.LongEventHandler:<UpdateCurrentAsynchronousEvent>m__84C()

should be here
Verse.Log:Error(String)
ExtendedStorage.Building_ExtendedStorage:TryMoveItem()
ExtendedStorage.Building_ExtendedStorage:Tick()
Verse.TickList:Tick()
Verse.TickManager:DoSingleTick()
Verse.TickManager:TickManagerUpdate()
Verse.Game:UpdatePlay()
Verse.Root_Play:Update()