#bananique bot shenanigans
1 messages · Page 1 of 1 (latest)
@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))]
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:
-
Access the
UnitStateParameter:
The original method signature isGetAttack(UnitState unit, GameState gameState). In your patch, capture this parameter. -
Check Unit Type:
UseEnumCache<UnitData.Type>.GetType("unit_name")to get the target unit type from the game's enum values. -
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:
-
Parameter Capture:
The patch method mirrors the original method's parameters (unitandgameState), allowing you to inspect the unit attacking. -
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").
- Replace
- Result Modification:
__resultholds 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 withreturn false). - Performance: Checks are lightweight since
EnumCacheuses 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.
@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
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:
-
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
- Original method was
-
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)
- Tech name:
-
Missing Debugging:
- Added
UnityEngine.Debug.Logto verify the patch executes - Check Unity console when researching tech and moving units
- Added
- Parameter Order:
- Correct parameter order:
(UnitState unitState, GameState gameState, ref int __result) - Must match original method signature exactly
- Correct parameter order:
Verification Steps:
-
Check Enum Names:
- Look in your game's
GameLogicData.jsonfor exact tech/enum names - Common Vampire tech is usually named
"VampirismGN" - Units are typically
"BatGN"and"VampireGN"
- Look in your game's
-
Test Conditions:
- Research the tech
- Have one of the specified units selected
- Open Unity console (View > Debug > Console) to see debug messages
-
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:
- Case Sensitivity: Game enums are case-sensitive
- Patch Loading: Confirm BepInEx loads your mod (check BepInEx log)
- Tech Requirements: Ensure the tech is actually researched in-game
- 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.
@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?
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:
- Patch Method: Target unit placement/movement methods
- Condition Checks: Unit type, player tech, terrain, etc.
- Improvement Placement: Create improvement state on the tile
- 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:
- Discrete Abilities:
- Improvements with
DiscreteAbility.Type.Improvementcan be placed by units- Use
HasDiscreteAbility()to check this property - Common improvements: Forts, Watchtowers, specific tribal improvements
- Use
-
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 }; } } - Always use
-
Terrain Restrictions:
- Add terrain checks:
// Can only place on specific terrain if (tile.type != TerrainData.Type.Mountain && tile.type != TerrainData.Type.Field) { return false; } -
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:
- Tile Validation: Always check if the tile can accept improvements
- Player Ownership: Ensure improvements are owned by the correct player
- Compatibility: Test with other mods that modify unit behavior
- Performance: Avoid heavy calculations in patches
- 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.
THIS BOT IS SO BASED IT USED SETTLER AND BUILDER
plz rate usefulness
im not joking btw
All im wondering is
How much bullshit does it say
I already see so much weird stuff
a lot
alot
it doesnt know actionStack for example