Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eboreg2 patch 1 #4

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 7 additions & 15 deletions Disarm/DisarmingPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,21 @@ public static class DisarmingPatch
[HarmonyPatch(typeof(Disarming), nameof(Disarming.Disarm))]
public static void Postfix(GameObject Object, GameObject Disarmer, string DisarmerStat, GameObject DisarmingWeapon, GameObject __result)
{
if (__result == null || Object.pBrain == null)
if (__result == null || Object.Brain == null)
{
return;
}
if(Options.GetOption("OptionDisarmReequip") != "Yes")
{
return;
}
if(Object.IsPlayer())
{
return;
}
if (Options.GetOption("OptionReequipSearch") == "Yes")
{
Object.pBrain.PushGoal(new ReequipOrFindNew(__result));
Object.Brain.PushGoal(new ReequipOrFindNew(__result));
}
else
{
Object.pBrain.PushGoal(new EquipObject(__result));
Object.Brain.PushGoal(new EquipObject(__result));
}
}
}
Expand All @@ -57,19 +53,15 @@ static void ReequipHelper(GameObject who, GameObject what)
{
return;
}
if(who.IsPlayer())
{
return;
}
if (who?.pBrain != null && what != null)
if (who?.Brain != null && what != null)
{
if (Options.GetOption("OptionReequipSearch") == "Yes")
{
who.pBrain.PushGoal(new ReequipOrFindNew(what));
who.Brain.PushGoal(new ReequipOrFindNew(what));
}
else
{
who.pBrain.PushGoal(new EquipObject(what));
who.Brain.PushGoal(new EquipObject(what));
}
}
}
Expand Down Expand Up @@ -136,4 +128,4 @@ static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> inst
return codes;
}
}
}
}
6 changes: 3 additions & 3 deletions Equip/EquipObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public override bool CanFight()

public override bool Finished()
{
return GameObject.validate(targetObject) && ParentObject.Contains(targetObject);
return GameObject.Validate(targetObject) && ParentObject.Contains(targetObject);
}

private void DoFail()
Expand All @@ -54,7 +54,7 @@ protected virtual void OnFail()

public override void TakeAction()
{
if (!GameObject.validate(targetObject))
if (!GameObject.Validate(targetObject))
{
Think($"What I was trying to equip no longer exists!");
DoFail();
Expand Down Expand Up @@ -105,4 +105,4 @@ public override void TakeAction()
}
}
}
}
}
4 changes: 2 additions & 2 deletions Equip/SearchForWeapon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public override void TakeAction()
}

int searchRadius = XRL.Rules.Stat.Random(ParentBrain.MinKillRadius, ParentBrain.MaxKillRadius);
List<GameObject> equipCandidates = CurrentZone.FastFloodVisibility(CurrentCell.X, CurrentCell.Y, searchRadius, searchPart, ParentObject).Where(GO => GO.CurrentCell != null && GO.IsTakeable() && CurrentCell.PathDistanceTo(GO.CurrentCell.location) <= searchRadius && scorerPredicate(GO) > maxScore).OrderByDescending(scorerPredicate).ToList();
List<GameObject> equipCandidates = CurrentZone.FastFloodVisibility(CurrentCell.X, CurrentCell.Y, searchRadius, searchPart, ParentObject).Where(GO => GO.CurrentCell != null && GO.IsTakeable() && CurrentCell.PathDistanceTo(GO.CurrentCell.Location) <= searchRadius && scorerPredicate(GO) > maxScore).OrderByDescending(scorerPredicate).ToList();
if (equipCandidates.Count() <= 0)
{
ParentBrain.DoReequip = true;
Expand All @@ -56,4 +56,4 @@ public override void TakeAction()
ParentBrain.PushGoal(new EquipObject(equipCandidates.First())); // if we don't get it, don't search again.
}
}
}
}
46 changes: 23 additions & 23 deletions SmartUse/FiringConePatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static class FiringConePatch
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var codes = new List<CodeInstruction>(instructions);
LocalBuilder local10 = (LocalBuilder) codes.Find(x => x.opcode == OpCodes.Ldloc_S && ((LocalBuilder)x.operand).LocalIndex == (byte) 10).operand;
LocalBuilder local9 = (LocalBuilder) codes.Find(x => x.opcode == OpCodes.Ldloc_S && ((LocalBuilder)x.operand).LocalIndex == (byte) 9).operand;
int callidx = codes.FindIndex(x => x.Calls(AccessTools.Method(typeof(Zone), "Line")));
int startidx = callidx - 8;
if (callidx == -1)
Expand All @@ -43,15 +43,16 @@ static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> inst
}
codes[callidx] = CodeInstruction.Call(typeof(FiringConePatch), nameof(GetFiringCone));
// ldarg.0; call get ParentObject
// ldloc.0;
// ldloc.s 10
// ldarg.0; call get Target
// ldloc.s 9
// List<Label> labels = new List<Label>(codes[startidx].labels); // there aren't actually any labels there
codes.RemoveRange(startidx, 8);
codes.InsertRange(startidx, new List<CodeInstruction> {
new CodeInstruction(OpCodes.Ldarg_0),
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(Kill), nameof(Kill.ParentObject))),
new CodeInstruction(OpCodes.Ldloc_0),
new CodeInstruction(OpCodes.Ldloc_S, local10)
new CodeInstruction(OpCodes.Ldarg_0),
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(Kill), nameof(Kill.Target))),
new CodeInstruction(OpCodes.Ldloc_S, local9)
});
// codes[startidx].labels = labels;
// now we replace IsHostileTowards.
Expand All @@ -62,7 +63,6 @@ static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> inst
}
codes[hostileidx].operand = AccessTools.Method(typeof(Bystander), nameof(Bystander.IsBystander));
codes[hostileidx+1].opcode = OpCodes.Brfalse_S;
codes.Insert(hostileidx, new CodeInstruction(OpCodes.Ldc_I4_0)); // don't include self
return codes;
}

Expand All @@ -82,9 +82,11 @@ static List<Point> GetFiringCone(GameObject firingObject, GameObject targetObjec
bool isSkilled = missileWeapon.IsSkilled(firingObject);
bool doVarianceCompensation = firingObject.Stat("Intelligence") >= 18 || firingObject.HasSkill("Tactics") || isSkilled || combatRole == "Artillery";
double aimPenalty = -firingObject.StatMod(missileWeapon.Modifier);
double unskilledPenalty = (doVarianceCompensation || missileWeaponObject.IsNatural()) ? 1 : 3; // if you aren't familiar with it you underestimate it
aimPenalty += ((double) missileWeapon.WeaponAccuracy / unskilledPenalty); // account for its inherent inaccuracy
aimPenalty -= ((double) missileWeaponObject.GetIntProperty("MissileWeaponAccuracyBonus") / unskilledPenalty); // and its inherent accuracy
if (doVarianceCompensation || missileWeaponObject.IsNatural())
{
aimPenalty += missileWeapon.WeaponAccuracy; // we're familiar enough with it to account for its inherent inaccuracy
aimPenalty -= missileWeaponObject.GetIntProperty("MissileWeaponAccuracyBonus"); // and its inherent accuracy
}
if (isSkilled)
{
aimPenalty -= 2;
Expand All @@ -100,30 +102,28 @@ static List<Point> GetFiringCone(GameObject firingObject, GameObject targetObjec
{
const double varianceStdDev = 4.72; // bad hardcoded numbers based on the |2d20-21| variance calculation
const double varianceMean = 6.65; // ditto
// UnityEngine.Debug.Log($"Variance compensation for {firingObject.DebugName}: {(int)(2*(varianceMean + varianceStdDev))}");
UnityEngine.Debug.Log($"Variance compensation for {firingObject.DebugName}: {(int)(2*(varianceMean + varianceStdDev))}");
aimPenalty += varianceMean + varianceStdDev; // in case we wanna up it to two standard deviations later
}
// UnityEngine.Debug.Log($"Aim penalty for {firingObject.DebugName}: {aimPenalty}");
if(aimPenalty == 0) // Cone doesn't currently work properly with an angle of 0.
{
return Zone.Line(currentCell.X, currentCell.Y, targetCell.X, targetCell.Y);
}
Location2D startLocation = currentCell.location;
Location2D endLocation = targetCell.location;
UnityEngine.Debug.Log($"Aim penalty for {firingObject.DebugName}: {aimPenalty}");
Location2D startLocation = currentCell.Location;
Location2D endLocation = targetCell.Location;
List<Location2D> result = new List<Location2D>();
// UnityEngine.Debug.Log($"Firing distance for {firingObject.DebugName}: {currentCell.PathDistanceTo(targetCell) + 1}");
GetCone(startLocation, endLocation, currentCell.PathDistanceTo(targetCell) + 1, (int) (aimPenalty * 2), result); // * 2 because it's both sides
ScreenBuffer Buffer = ScreenBuffer.GetScrapBuffer1();
if (Options.GetOption("OptionFiringConeDebug", "No") == "Yes" && firingObject.InActiveZone())
if (Options.GetOption("OptionFiringConeDebug", "No") == "Yes")
{
while (true)
{
Buffer.RenderBase();
for (int l = 0; l < result.Count; l++)
{
Buffer.Goto(result[l].x, result[l].y);
Buffer.Goto(result[l].X, result[l].Y);
Cell cell3 = currentCell.ParentZone.GetCell(result[l]);
Buffer.Write("&CX");
if (l < result.Count - 1)
{
Buffer.Write("&CX");
}
}
Buffer.Draw();
if (Keyboard.kbhit())
Expand All @@ -132,7 +132,7 @@ static List<Point> GetFiringCone(GameObject firingObject, GameObject targetObjec
}
}
}
return result.Select(location => new Point(location.x, location.y)).ToList();
return result.Select(location => new Point(location.X, location.Y)).ToList();
}
}
}
}
58 changes: 28 additions & 30 deletions SmartUse/MissilePatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using XRL.World.AI;
using System.Linq;
using XRL.UI;
using LiveAndThink.Logic;

/// <summary>
/// A collection of Harmony patches that make creatures
Expand Down Expand Up @@ -79,28 +78,12 @@ static bool MissileSafetyCheck(GameObject missileWeapon, Brain shooterBrain, Cel
}
GameObject projectile = null;
string blueprint = null;
// We need a special exception here to handle stuff like bows and launchers
// that use existing objects as projectiles instead of just summoning them from a blueprint.
MagazineAmmoLoader magazineAmmoLoader = missileWeapon.GetPart<MagazineAmmoLoader>();
if (magazineAmmoLoader != null)
{
projectile = GetProjectileObjectEvent.GetFor(magazineAmmoLoader.Ammo, missileWeapon);
if (projectile != null && projectile.IsInvalid())
{
projectile = null; // try again
}
}
// If we still don't have a projectile, try the normal event
GetMissileWeaponProjectileEvent.GetFor(missileWeapon, ref projectile, ref blueprint);
if (projectile == null)
{
GetMissileWeaponProjectileEvent.GetFor(missileWeapon, ref projectile, ref blueprint);
// If we don't have one after that, create a sample object from the ammo blueprint
if (projectile == null && blueprint != null)
{
projectile = GameObject.createSample(blueprint);
}
projectile = GameObject.CreateSample(blueprint);
}
if(!GameObject.validate(projectile) || projectile.IsInGraveyard())
if(!GameObject.Validate(projectile) || projectile.IsInGraveyard())
{
UnityEngine.Debug.Log($"Missile weapon {missileWeapon.DebugName} has no projectile!");
return true;
Expand All @@ -117,9 +100,9 @@ static bool MissileSafetyCheck(GameObject missileWeapon, Brain shooterBrain, Cel
List<GameObject> bystanders = targetCell.FastFloodVisibility("Combat", dangerRadius);
foreach (GameObject bystander in bystanders)
{
UnityEngine.Debug.Log($"Thrower {shooterBrain.ParentObject.DebugName} is {shooterBrain.GetOpinion(bystander)} to {bystander.DebugName}");
UnityEngine.Debug.Log($"Thrower {shooterBrain.ParentObject.DebugName} is {shooterBrain.GetFeelingLevel(bystander)} to {bystander.DebugName}");
UnityEngine.Debug.Log($"Bystander {bystander.DebugName} {(CanEndangerAlly(projectile, bystander) ? "can" : "cannot")} be damaged by {projectile.GetType().Name}");
if (shooterBrain.IsBystander(bystander, includeSelf: true) && CanEndangerAlly(projectile, bystander))
if (!shooterBrain.IsHostileTowards(bystander) && CanEndangerAlly(projectile, bystander))
{
return false;
}
Expand All @@ -139,10 +122,9 @@ static bool MissileSafetyCheck(GameObject missileWeapon, Brain shooterBrain, Cel
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
var codes = new List<CodeInstruction>(instructions);
CodeInstruction ld10 = codes.Find(x => x.opcode == OpCodes.Ldloc_S && ((LocalBuilder)x.operand).LocalIndex == (byte) 10);
LocalBuilder local10 = (LocalBuilder) ld10.operand;
LocalBuilder local9 = (LocalBuilder) codes.Find(x => x.opcode == OpCodes.Ldloc_S && ((LocalBuilder)x.operand).LocalIndex == (byte) 9).operand;
int bridx = -1;
for (int i=codes.IndexOf(ld10); i<codes.Count; i++)
for (int i=codes.FindIndex(x => x.Is(OpCodes.Ldstr, "AIWantUseWeapon")); i<codes.Count; i++)
{
if (codes[i].opcode == OpCodes.Brfalse)
{
Expand All @@ -156,18 +138,34 @@ static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> inst
}
CodeInstruction leaveInstruction = codes[bridx].Clone();
codes.InsertRange(bridx+1, new CodeInstruction[] {
// ldloc.s local10
new CodeInstruction(OpCodes.Ldloc_S, local10),
// ldloc.s local9
new CodeInstruction(OpCodes.Ldloc_S, local9),
// ldarg.0
// ldfld class XRL.Game.Brain XRL.Game.AI.GoalHandler::ParentBrain
new CodeInstruction(OpCodes.Ldarg_0),
CodeInstruction.LoadField(typeof(GoalHandler), nameof(GoalHandler.ParentBrain)),
// ldloc.3
new CodeInstruction(OpCodes.Ldloc_3),
// ldloc.2
new CodeInstruction(OpCodes.Ldloc_2),
// call MissilePatch::MissileSafetyCheck(GameObject, Brain, Cell)
CodeInstruction.Call(typeof(MissilePatch), nameof(MissileSafetyCheck)),
leaveInstruction});
return codes;
}

/// <summary>
/// Modify MagazineAmmoLoader.HandleEvent(GetMissileWeaponProjectileEvent E) to work with bows and launchers
/// by setting E.Projectile to Ammo.GetProjectileObjectEvent.GetFor(Ammo, ParentObject) if Ammo is valid/non-null.
/// </summary>
[HarmonyPatch(typeof(MagazineAmmoLoader), nameof(MagazineAmmoLoader.HandleEvent), new Type[] { typeof(GetMissileWeaponProjectileEvent) })]
static bool Prefix(MagazineAmmoLoader __instance, GetMissileWeaponProjectileEvent E, ref bool __result)
{
if (__instance.Ammo != null && __instance.Ammo.IsValid())
{
E.Projectile = GetProjectileObjectEvent.GetFor(__instance.Ammo, __instance.ParentObject);
__result = false;
return false;
}
return true;
}
}
}
}
5 changes: 2 additions & 3 deletions SmartUse/QuillsPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using HarmonyLib;
using XRL.World.Parts.Mutation;
using XRL.UI;
using LiveAndThink.Logic;

/// <summary>
/// A collection of Harmony patches that make creatures
Expand Down Expand Up @@ -34,7 +33,7 @@ static bool QuillsFriendSafetyCheck(Quills quills)
{
foreach (GameObject bystander in cell.GetObjectsWithPartReadonly("Combat"))
{
if (bystander.HasPart("Combat") && !(bystander.GetPart<XRL.World.Parts.Mutations>()?.HasMutation("Quills") ?? false) && (quills.ParentObject.pBrain?.IsBystander(bystander) ?? false))
if (bystander.HasPart("Combat") && !(bystander.GetPart<XRL.World.Parts.Mutations>()?.HasMutation("Quills") ?? false) && !quills.ParentObject.Brain.IsHostileTowards(bystander))
{
return false;
}
Expand Down Expand Up @@ -72,4 +71,4 @@ static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> inst
return codes;
}
}
}
}