Skip to content

Releases: Arcitectus/Timon

release v16.02.21

22 Mar 08:54
Compare
Choose a tag to compare

sample script:

//  This script searches for objects by color and attacks if the "Attack" action is offered when the mouse is moved over the object.

using System;
using SmartNet.Extension;
using Timon;
using Bib3.Geometrik;

var colorToAttackR = 37;
var colorToAttackG = 31;
var colorToAttackB = 18;
var colorToAttackTolerance = 5;

var viewportRect = new RectInt(26, 4, 520, 338);

var charSelfHealthBarRegion = RectInt.FromCenterAndSize(viewportRect.Center(), new Vektor2DInt(60, 60));

var findTextAttackTolerance = 0x40;

/// <summary>
/// The "Att" from "Attack" taken from a screenshot.
/// </summary>
static readonly string[] setPatternAttackGreySerial = new[] {
    @"iVBORw0KGgoAAAANSUhEUgAAABUAAAALCAYAAACQy8Z9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuOBs0TtgAAABuSURBVDhPlc1BDoBACENR7n9CbqOiA0Hsn8RFjXmtaO6eOVq6/06+3MfMjA4rQ68iDq6jalybZuhUTFMb9CpU5tGWPCC9ijiQ6RYj2KC/ioCVaWqDTsU0tUGnYpraoFOBtpIm/XlcH3/+trG9u51ieVj37ZfS5AAAAABJRU5ErkJggg==",
    @"iVBORw0KGgoAAAANSUhEUgAAABUAAAALCAYAAACQy8Z9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuOBs0TtgAAABxSURBVDhPxZDBDcAwCAPZf0K2oSIC5IJpn3lYig5zSiKqmjEI8jVmRnkejkxENjFjKR2zgi4MKStWB9hLirNtoTPW+ZeydClkSCHz+SEq5qWlM25aQejFSGesc+lPb0iLRQ4L6Zgd6MtN8MmSgxRmYg8fIF3+RpmKeAAAAABJRU5ErkJggg==",
    @"iVBORw0KGgoAAAANSUhEUgAAABUAAAALCAYAAACQy8Z9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuOBs0TtgAAABuSURBVDhP1c5BDoAwCARA/v9CfoPSAFkoVOPNw6btBFaJmT0CQScRSe8n98sqI6K22JZfe6AWWuk2iMswM3qL1T6XdulKIaOnL3nQdKj+kWfyhPep783qstrJW6z2u9Jwy+gLdbmUJoPlcE3vJBdUb2MFrXWxUgAAAABJRU5ErkJggg==",
};

var setPatternAttackRaster = setPatternAttackGreySerial.Select(serial => Convert.FromBase64String(serial).RasterORGBFromFile()).ToArray();

var setPatternAttackPredicate = setPatternAttackRaster.Select(raster => raster.Value.RasterMatchAtOffsetPredicateBinary(findTextAttackTolerance)).ToArray();

var findColorPredicate = RasterImagePatternMatch.ColorAtOffsetPredicateBinary(colorToAttackR, colorToAttackG, colorToAttackB, colorToAttackTolerance);

var smartSession = Timon.SmartSession;

var findTextAttack = new Func<KeyValuePair<UInt32[], int>, RectInt, IEnumerable<Vektor2DInt>>((raster, region) =>
    setPatternAttackPredicate.Select(pattern => raster.FindSetMatchInRegion(pattern, region))
    .ConcatNullable());

var healthBarPredicate = RasterImagePatternMatch.HealthBarAtOffsetPredicateBinary();

var getTime = new Func<Int64>(Host.GetTimeContinuousMilli);

int randomInt() => new Random((int)getTime()).Next();

Int64 healthBarLastSeenTime = 0;

for(;;)
{
    try
    {
        var screenshot = smartSession.TakeImageRaster();

        if (!screenshot.HasValue)
            continue;

        if (!screenshot.Value.FindSetMatchInRegion(healthBarPredicate, charSelfHealthBarRegion).IsNullOrEmpty())
            healthBarLastSeenTime = getTime();

        var healthBarLastSeenAge = (getTime() - healthBarLastSeenTime) / 1000;

        Host.Log("health bar last seen age: " + healthBarLastSeenAge);

        if (healthBarLastSeenAge < 5)
            continue;   //  assume we are still in a fight, therefore just wait.

        var colorSetMatchLocation =
            screenshot.Value.FindSetMatchInRegion(findColorPredicate, viewportRect)?.ToArray();

        if (!(0 < colorSetMatchLocation?.Length))
            continue;

        //  pick a random pixel of the set of pixel matching the color.
        var testLocation =
            colorSetMatchLocation?.CastToNullable()
            ?.ElementAtOrDefault(randomInt() % colorSetMatchLocation.Length);

        if (!testLocation.HasValue)
            continue;   //  no pixel in the searched region matches the color description.

        smartSession.MouseMove((int)testLocation.Value.A, (int)testLocation.Value.B);

        Host.Delay(333);

        screenshot = smartSession.TakeImageRaster();

        if (!screenshot.HasValue)
            continue;

        //  search for Attack text in the upper left.
        var mouseOverAttackMatch =
            findTextAttack(screenshot.Value, new RectInt(0, 0, 100, 80))
            ?.CastToNullable()
            ?.FirstOrDefault();

        Host.Delay(333);

        if (!mouseOverAttackMatch.HasValue)
            continue;   //  no Attack text found.

        smartSession.MouseClickRight((int)testLocation.Value.A, (int)testLocation.Value.B);

        Host.Delay(333);

        //  now the menu for the object should be open.
        screenshot = smartSession.TakeImageRaster();

        if (!screenshot.HasValue)
            continue;

        //  search for attack text
        var attackMatch =
            findTextAttack(screenshot.Value, viewportRect)
            ?.CastToNullable()
            ?.FirstOrDefault();

        if (attackMatch.HasValue)
        {
            //  assume the found text belongs to the context menu. Click on the menu entry.
            smartSession.MouseClickLeft((int)attackMatch.Value.A + 10, (int)attackMatch.Value.B + 4);
            Host.Delay(4444); //    wait for char to arrive there.
        }
    }
    finally
    {
        Host.Delay(1111);
    }
}