[HELP] Shoot over an impassable structure/Place Gate over Fence blueprint.

Started by JessiBeau, August 29, 2018, 12:05:26 AM

Previous topic - Next topic

JessiBeau

Hi there, I'm currently working on something and am trying to figure out which part of the xml allows pawns to shoot over a structure? Say it's a fence that I'm making, I want it to be impassable, but I'd like my pawns to still be able to shoot over it. I'm guessing it's something simple, but my brain is just not "braining" today, I suppose.

Thanks in advance!
JB

EDIT---

Figured the shooting over it out by taking a look at both the sandbag code and the wall code and winging it. So now I can place it, drag it like you can a wall, but I cannot seem to place a gate over a fence blueprint like you can a door over a wall blueprint. I have to cancel the fence blueprint to place a gate. :/ Any help with this one?
Learning to mod. My eyeballs hurt.

LWM

If no one here can answer for you, you might check out any of the embrasure mods to see how they did it.

--LWM

JessiBeau

Quote from: LWM on August 29, 2018, 12:37:59 AM
If no one here can answer for you, you might check out any of the embrasure mods to see how they did it.

--LWM

Thanks! I actually figured it out myself. I just kind of winged it and looked at both the sandbags and the wall code and went from there. Now it works. My only issue now is that when I drag a fence, get it just how I want it, like you would a wall, then go to place the gate, it won't place over it, I have to cancel the fence blueprint wherever I want to place a gate. Sigh.
Learning to mod. My eyeballs hurt.

LWM


JessiBeau

No. From what I can tell with my extremely limited C# knowledge- The door calls for <canPlaceOverWall>, the fence does not count itself in that. Looking at the c# code I believe these are the relevant areas. Am I correct in that?

public bool canPlaceOverWall; public static BuildableDef BuiltDefOf(ThingDef def)
        {
            return (def.entityDefToBuild == null) ? def : def.entityDefToBuild;
        }

        // Token: 0x0600379B RID: 14235 RVA: 0x001A5DB4 File Offset: 0x001A41B4
        public static bool CanPlaceBlueprintOver(BuildableDef newDef, ThingDef oldDef)
        {
            if (oldDef.EverHaulable)
            {
                return true;
            }
            TerrainDef terrainDef = newDef as TerrainDef;
            if (terrainDef != null)
            {
                if (oldDef.category == ThingCategory.Building && !terrainDef.affordances.Contains(oldDef.terrainAffordanceNeeded))
                {
                    return false;
                }
                if ((oldDef.IsBlueprint || oldDef.IsFrame) && !terrainDef.affordances.Contains(oldDef.entityDefToBuild.terrainAffordanceNeeded))
                {
                    return false;
                }
            }
            ThingDef thingDef = newDef as ThingDef;
            BuildableDef buildableDef = GenConstruct.BuiltDefOf(oldDef);
            ThingDef thingDef2 = buildableDef as ThingDef;
            if (oldDef == ThingDefOf.SteamGeyser && !newDef.ForceAllowPlaceOver(oldDef))
            {
                return false;
            }
            if (oldDef.category == ThingCategory.Plant && oldDef.passability == Traversability.Impassable && thingDef != null && thingDef.category == ThingCategory.Building && !thingDef.building.canPlaceOverImpassablePlant)
            {
                return false;
            }
            if (oldDef.category == ThingCategory.Building || oldDef.IsBlueprint || oldDef.IsFrame)
            {
                if (thingDef != null)
                {
                    if (!thingDef.IsEdifice())
                    {
                        return (oldDef.building == null || oldDef.building.canBuildNonEdificesUnder) && (!thingDef.EverTransmitsPower || !oldDef.EverTransmitsPower);
                    }
                    if (thingDef.IsEdifice() && oldDef != null && oldDef.category == ThingCategory.Building && !oldDef.IsEdifice())
                    {
                        return thingDef.building == null || thingDef.building.canBuildNonEdificesUnder;
                    }
                    if (thingDef2 != null && (thingDef2 == ThingDefOf.Wall || thingDef2.IsSmoothed) && thingDef.building != null && thingDef.building.canPlaceOverWall)
                    {
                        return true;
                    }
                    if (newDef != ThingDefOf.PowerConduit && buildableDef == ThingDefOf.PowerConduit)
                    {
                        return true;
                    }
                }
                return (newDef is TerrainDef && buildableDef is ThingDef && ((ThingDef)buildableDef).CoexistsWithFloors) || (buildableDef is TerrainDef && !(newDef is TerrainDef));
            }
            return true;

Learning to mod. My eyeballs hurt.

LWM

Oh, hmm.  thingDef2 is the old thing and thingDef is the new thing (ish):
So if (the old thing is a Wall or IsSmoothed (that new mechanic for smoothing stone walls?)) and you canPlaceOverWall, then allow it.  But your thing isn't a Wall...

                    if (thingDef2 != null && (thingDef2 == ThingDefOf.Wall || thingDef2.IsSmoothed) && thingDef.building != null && thingDef.building.canPlaceOverWall)
                    {
                        return true;
                    }


Can you make your fence "IsSmoothed"?  That might be possible in XML?  And might not even affect too much!

Otherwise, patching with Harmony looks easy ^.^  (Says the person who's done a lot of Harmon patching the last few weeks :p )

--LWM

JessiBeau

Hmmmmm, that sounds like something that might work. I won't be able to sit down at my pc until lunch time or so. But I'll give that a try then and let you know how it works!


I have one more question, if you don't mind. I have a few place workers I need to code, and I'm able to figure most of the c# stuff by reading the core assembly. But one thing I'm confused by is when you tell the game to generate, for example, an acceptance report that will give one of those messages in the top left (ie the terrain here cannot support this) typically it says something along the lines in the code of: generate AcceptanceReport (NeedsRoof) (that's not exact I just don't have the pc in front of me. So that (NeedsRoof) is what tells it what message to pop up, right? Where is the string that tells it what to say in the message? Like where would I define NeedsRoof to pop up and say, "This item needs a roof" or something?

-Edit-
Alright I took a moment and combed through the xml. Looks like it's not a simple <isSmoothed> or something. Essentially the rough sandstone has a tag that says <smoothedThing>SmoothedSanstone</smoothedThing>> Then the ThingDef SmoothedSandstone is defined below that. Going to attempt to find a way to make that work. Might end up having to be coded in C# though/
Learning to mod. My eyeballs hurt.

LWM

Those messages in the upper left?  I know in B18 the syntax in the code was something like
    Messages.Message(s, MessageTypeDefOf.NeutralEvent);
"s" here is a string....but that's not easy to translate.  So you'd do something like this:
Messages.Message("RecipeCannotHaveTargetCount".Translate(), MessageTypeDefOf.RejectInput, false);

And you'd have XML in the Languages/English directory that has the actual text.  A good general idea for figuring out how such things work?  Search.  Search for the string in the entire code base.  Search for the string in all the xml files in RimWorld/Mods/Core/ (maybe only .../Core/Defs and .../Core/Languages/English or whatever).  Every platform has some way to do it; I only know Linux ^.^

Hope that helps, good luck with the smoothed XML!

--LWM