#bananique bot shenanigans

1 messages · Page 1 of 1 (latest)

oblique dew
#

anything i ask the bot i will ask here

#

@hoary imp how do i check for a certain unit type, within the following parameters: [HarmonyPatch(typeof(UnitDataExtensions), nameof(UnitDataExtensions.GetAttack), typeof(UnitState), typeof(GameState))]

hoary impBOT
# oblique dew <@1375000903962067044> how do i check for a certain unit type, within the follow...

To check for a specific unit type within your Harmony patch for UnitDataExtensions.GetAttack, you can access the UnitState parameter and compare its type. Here's a structured approach:

Key Steps:

  1. Access the UnitState Parameter:
    The original method signature is GetAttack(UnitState unit, GameState gameState). In your patch, capture this parameter.

  2. Check Unit Type:
    Use EnumCache<UnitData.Type>.GetType("unit_name") to get the target unit type from the game's enum values.

  3. Modify Behavior (Optional):
    Use the check to alter the result (__result) or execute custom logic.


Example Implementation:

using HarmonyLib;
using Polytopia.Data;

[HarmonyPatch]
public static class UnitAttackPatches
{
    [HarmonyPostfix]
    [HarmonyPatch(typeof(UnitDataExtensions), nameof(UnitDataExtensions.GetAttack), typeof(UnitState), typeof(GameState))]
    private static void UnitDataExtensions_GetAttack_Postfix(
        ref int __result, 
        UnitState unit, 
        GameState gameState
    )
    {
        // Step 1: Get the target unit type (e.g., "warrior")
        UnitData.Type targetUnitType = EnumCache<UnitData.Type>.GetType("warrior");
        
        // Step 2: Check if the current unit matches the target type
        if (unit.type == targetUnitType)
        {
            // Step 3: Modify behavior (e.g., double the attack)
            __result *= 2;
            
            // Optional: Log the change
            UnityEngine.Debug.Log($"Warrior attack boosted to: {__result}");
        }
    }
}

Explanation:

  1. Parameter Capture:
    The patch method mirrors the original method's parameters (unit and gameState), allowing you to inspect the unit attacking.

  2. Unit Type Check:

#
  • EnumCache<UnitData.Type>.GetType("warrior") fetches the enum value for the unit type named "warrior" in the game's data.
    • Replace "warrior" with your target unit type (e.g., "archer", "giant1").
  1. Result Modification:
    • __result holds the original attack value.
    • Modify it directly (e.g., __result *= 2) to change the outcome for matching units.

Advanced: Conditional Logic

Add more complex conditions using gameState or unit properties:

if (unit.type == targetUnitType && unit.owner == gameState.CurrentPlayer.Id)
{
    __result += 10; // Bonus attack for player's warriors
}

Notes:

  • Unit Type Names: Use lowercase strings matching the game's JSON data (e.g., "warrior", "giant1").
  • Patch Type: Use [HarmonyPostfix] to modify results after the original method runs. For full control, use [HarmonyPrefix] (but skip the original method with return false).
  • Performance: Checks are lightweight since EnumCache uses cached enum lookups.

This approach ensures you reliably target specific units and modify their behavior within the combat system.

#

-# ⚙️ PolyModder (v3.1.0) can make mistakes, please verify the information provided.

oblique dew
#

@hoary imp

    [HarmonyPatch(typeof(UnitDataExtensions), nameof(UnitDataExtensions.GetAttack), typeof(UnitState), typeof(GameState))]
    public static void Empowerment(this UnitState unitState, GameState gameState, ref int __result)
    {
        var success = gameState.TryGetPlayer(unitState.owner, out PlayerState player);
        if(success) {
            if(player.HasTech(EnumCache<TechData.Type>.GetType("vampirismsgn")))
            {
                if(unitState.type == EnumCache<UnitData.Type>.GetType("batsgn")||unitState.type == EnumCache<UnitData.Type>.GetType("vampiresgn"))
                {
                    __result = __result + 50;
                }
            }
        }
    }```

the attack of the units specified dont increase in-game when i research the specified tech
hoary impBOT
# oblique dew <@1375000903962067044> ```[HarmonyPostfix] [HarmonyPatch(typeof(UnitDataExt...

Based on your code, I can identify several issues that prevent the attack boost from working in-game. Here's the corrected patch with explanations:

Corrected Patch:

[HarmonyPostfix]
[HarmonyPatch(typeof(UnitDataExtensions), nameof(UnitDataExtensions.GetAttack), typeof(UnitState), typeof(GameState))]
public static void GetAttack_Postfix(UnitState unitState, GameState gameState, ref int __result)
{
    // Get player state first
    if (gameState.TryGetPlayer(unitState.owner, out PlayerState player))
    {
        // Check for tech using correct enum name
        if (player.HasTech(EnumCache<TechData.Type>.GetType("VampirismGN")))
        {
            // Check unit types using correct names
            if (unitState.type == EnumCache<UnitData.Type>.GetType("BatGN") || 
                unitState.type == EnumCache<UnitData.Type>.GetType("VampireGN"))
            {
                // Apply the boost
                __result += 50;
                
                // Optional: Debug log
                UnityEngine.Debug.Log($"Vampirism boost applied! Attack: {__result}");
            }
        }
    }
}

Key Fixes:

  1. Method Signature Issue:

    • Original method was Empowerment(this UnitState... which is invalid for Harmony patches
    • Fixed to: public static void GetAttack_Postfix(...)
    • Must be static and match original parameters + ref __result
  2. Enum Name Capitalization:

    • Tech name: "vampirismsgn""VampirismGN"
    • Unit names: "batsgn""BatGN", "vampiresgn""VampireGN"
    • Game uses PascalCase for enum identifiers (check your game's JSON files)
  3. Missing Debugging:

    • Added UnityEngine.Debug.Log to verify the patch executes
    • Check Unity console when researching tech and moving units
#
  1. Parameter Order:
    • Correct parameter order: (UnitState unitState, GameState gameState, ref int __result)
    • Must match original method signature exactly

Verification Steps:

  1. Check Enum Names:

    • Look in your game's GameLogicData.json for exact tech/enum names
    • Common Vampire tech is usually named "VampirismGN"
    • Units are typically "BatGN" and "VampireGN"
  2. Test Conditions:

    • Research the tech
    • Have one of the specified units selected
    • Open Unity console (View > Debug > Console) to see debug messages
  3. Combat Testing:

    • Attack with the units while debug logging shows the patch is active
    • Compare damage numbers with/without the tech researched

Alternative Approach:

If issues persist, use this more robust version:

[HarmonyPostfix]
[HarmonyPatch(typeof(UnitDataExtensions), nameof(UnitDataExtensions.GetAttack))]
public static void GetAttack_Postfix(UnitState __instance, GameState __state, ref int __result)
{
    try
    {
        if (__state.TryGetPlayer(__instance.owner, out PlayerState player) &&
            player.HasTech(EnumCache<TechData.Type>.GetType("VampirismGN")) &&
            (__instance.type == EnumCache<UnitData.Type>.GetType("BatGN") || 
             __instance.type == EnumCache<UnitData.Type>.GetType("VampireGN")))
        {
            __result += 50;
        }
    }
    catch (Exception e)
    {
        UnityEngine.Debug.LogError($"Vampirism patch error: {e.Message}");
    }
}

Common Pitfalls:

  1. Case Sensitivity: Game enums are case-sensitive
  2. Patch Loading: Confirm BepInEx loads your mod (check BepInEx log)
  3. Tech Requirements: Ensure the tech is actually researched in-game
  4. Unit Types: Verify unit types exist in your game version
#

After applying these fixes, the attack bonus should appear when you research Vampirism and use Bat/Vampire units in combat. Check the Unity console for debug confirmation.

#

-# ⚙️ PolyModder (v3.1.0) can make mistakes, please verify the information provided.

oblique dew
#

@hoary imp how do i make a unit spawn an improvement on the tile when certain conditions are met, and does it work on other improvements if the improvement has the discrete ability?

hoary impBOT
# oblique dew <@1375000903962067044> how do i make a unit spawn an improvement on the tile whe...

To make a unit spawn an improvement when certain conditions are met, you'll need to create a Harmony patch that triggers during unit placement or movement. Here's a structured approach:

Key Components:

  1. Patch Method: Target unit placement/movement methods
  2. Condition Checks: Unit type, player tech, terrain, etc.
  3. Improvement Placement: Create improvement state on the tile
  4. Discrete Abilities: Handle improvements that have unit-placement abilities

Step-by-Step Implementation:

1. Create a Harmony Patch

Patch the Unit.Place method (called when units are placed on the map):

using HarmonyLib;
using Polytopia.Data;

[HarmonyPatch]
public static class UnitImprovementPatches
{
    [HarmonyPostfix]
    [HarmonyPatch(typeof(Unit), nameof(Unit.Place))]
    private static void UnitPlace_Postfix(Unit __instance, GameState gameState, WorldCoordinates coordinates)
    {
        // Get the tile where the unit is placed
        TileData tile = gameState.Map.GetTile(coordinates);
        
        // Check conditions
        if (ShouldSpawnImprovement(__instance, gameState, tile))
        {
            PlaceImprovementOnTile(gameState, tile, __instance.owner);
        }
    }
}

2. Implement Condition Logic

private static bool ShouldSpawnImprovement(Unit unit, GameState gameState, TileData tile)
{
    // Condition 1: Unit type check
    if (unit.type != EnumCache<UnitData.Type>.GetType("settler") && 
        unit.type != EnumCache<UnitData.Type>.GetType("builder"))
    {
        return false;
    }

    // Condition 2: No existing improvement
    if (tile.improvement != null)
    {
        return false;
    }

    // Condition 3: Player has required tech
#
    if (!gameState.TryGetPlayer(unit.owner, out PlayerState player))
        return false;
    
    if (!player.HasTech(EnumCache<TechData.Type>.GetType("construction")))
    {
        return false;
    }

    // Condition 4: Valid terrain (example: only on land)
    return tile.type != TerrainData.Type.Water && 
           tile.type != TerrainData.Type.Ocean;
}

3. Place the Improvement

private static void PlaceImprovementOnTile(GameState gameState, TileData tile, byte playerId)
{
    // Create improvement state
    ImprovementState improvement = new ImprovementState
    {
        type = EnumCache<ImprovementData.Type>.GetType("fort"),  // Target improvement
        level = 1,
        owner = playerId
    };

    // Apply to tile
    tile.improvement = improvement;
    
    // Optional: Add to action stack for compatibility
    gameState.ActionStack.Add(new CustomPlaceImprovementAction(
        playerId, 
        tile.coordinates, 
        improvement.type
    ));
}

4. Handle Discrete Abilities

For improvements that have discrete abilities (like DiscreteAbility.Type.Improvement):

private static bool ShouldSpawnImprovement(Unit unit, GameState gameState, TileData tile)
{
    // ... (previous conditions)
    
    // New: Check improvement's discrete ability
    ImprovementData improvementData;
    if (!gameState.GameLogicData.TryGetData(
        EnumCache<ImprovementData.Type>.GetType("fort"), 
        out improvementData))
    {
        return false;
    }

    // Check if improvement has unit-placement ability
    return improvementData.HasDiscreteAbility(DiscreteAbility.Type.Improvement);
}

Key Considerations:

  1. Discrete Abilities:
#
  • Improvements with DiscreteAbility.Type.Improvement can be placed by units
    • Use HasDiscreteAbility() to check this property
    • Common improvements: Forts, Watchtowers, specific tribal improvements
  1. Action System:

    • Always use gameState.ActionStack.Add() for consistency
    • Create custom actions for complex operations:
    public class CustomPlaceImprovementAction : ActionBase
    {
        public WorldCoordinates Coordinates { get; }
        public ImprovementData.Type ImprovementType { get; }
    
        public CustomPlaceImprovementAction(byte playerId, WorldCoordinates coords, ImprovementData.Type type)
            : base(playerId)
        {
            Coordinates = coords;
            ImprovementType = type;
        }
    
        public override void Execute(GameState state)
        {
            TileData tile = state.Map.GetTile(Coordinates);
            tile.improvement = new ImprovementState
            {
                type = ImprovementType,
                level = 1,
                owner = base.PlayerId
            };
        }
    }
    
  2. Terrain Restrictions:

    • Add terrain checks:
    // Can only place on specific terrain
    if (tile.type != TerrainData.Type.Mountain && 
        tile.type != TerrainData.Type.Field)
    {
        return false;
    }
    
  3. Tech Requirements:

    • Check specific techs:
    if (!player.HasTech(EnumCache<TechData.Type>.GetType("engineering")))
    {
        return false;
    }
    

Full Example with Discrete Abilities:

[HarmonyPostfix]
[HarmonyPatch(typeof(Unit), nameof(Unit.Place))]
private static void UnitPlace_Postfix(Unit __instance, GameState gameState, WorldCoordinates coordinates)
{
    TileData tile = gameState.Map.GetTile(coordinates);
    
#
    if (tile.improvement != null) return;
    
    if (!gameState.TryGetPlayer(__instance.owner, out PlayerState player)) return;
    
    // Check if unit is a "settler" type
    if (__instance.type != EnumCache<UnitData.Type>.GetType("settler")) return;
    
    // Get improvement data
    ImprovementData improvementData;
    if (!gameState.GameLogicData.TryGetData(
        EnumCache<ImprovementData.Type>.GetType("watchtower"), 
        out improvementData))
    {
        return;
    }
    
    // Check discrete ability and terrain
    if (improvementData.HasDiscreteAbility(DiscreteAbility.Type.Improvement) &&
        tile.type != TerrainData.Type.Water)
    {
        gameState.ActionStack.Add(new CustomPlaceImprovementAction(
            __instance.owner,
            coordinates,
            improvementData.type
        ));
    }
}

Important Notes:

  1. Tile Validation: Always check if the tile can accept improvements
  2. Player Ownership: Ensure improvements are owned by the correct player
  3. Compatibility: Test with other mods that modify unit behavior
  4. Performance: Avoid heavy calculations in patches
  5. Logging: Add debug logs to verify conditions:
    UnityEngine.Debug.Log($"Unit placed at {coordinates}: {__instance.type}");
    

This approach will let you spawn improvements when units are placed, with full support for discrete abilities and custom conditions.

#

-# ⚙️ PolyModder (v3.1.0) can make mistakes, please verify the information provided.

oblique dew
random parcel
#

im not joking btw

hushed comet
#

All im wondering is

#

How much bullshit does it say

#

I already see so much weird stuff

random parcel
sharp nest
#

it doesnt know actionStack for example