Results 1 to 12 of 12

Thread: Detecting if your interacting with an Npc

  1. #1
    Join Date
    Aug 2015
    Posts
    12
    Mentioned
    0 Post(s)
    Quoted
    5 Post(s)

    Default Detecting if your interacting with an Npc

    Is there a standard way for detecting if you're interacting with an npc with Reflection? this code acts exactly how I expect it would... But it crashes after about 30 seconds of use...

    Simba Code:
    program new;
    {$DEFINE SMART}
    {$i Reflection/Reflection.simba}

    var
    xOffset,yOffset: integer;
    ChickenBox: TBox;
    MyPlayer: TReflectLocalPlayer;
    Chicken: TReflectNpc;
    ChickenPoint: TPoint;
    Players: TReflectPlayerArray;
    Timer: TReflectTimer;
    smartWidth := 765;
    smartHeight := 502;
    Npcs: TReflectNpcArray;
    InteractingNpc: TReflectNpc;
    NullNpc: TReflectNpc;
    InteractingName: String;
    i,defxp,strxp,attxp: Integer;

    //================================~LogicLoop~===================================
    procedure LogicLoop
    begin
      Npcs.GetAll;
      Npcs.Sort;

      // code for checking if the npc is null
      InteractingNpc := NullNpc;
      MyPlayer.GetInteractingNpc(InteractingNpc);
      InteractingName := InteractingNpc.GetName();
      writeln(interactingnpc);


      for i := 0 to High(Npcs) do
      begin
        attxp := MyPlayer.GetSkillExp(0);
        defxp := MyPlayer.GetSkillExp(1);
        strxp := MyPlayer.GetSkillExp(2);
        if(Npcs[i].GetName = 'Chicken') and not (Npcs[i].IsUnderAttack)then
        begin
          //writeln(MyPlayer.GetSkillExp(2));
          //writeln(MyPlayer.GetAnimation());
          ChickenPoint := Npcs[i].GetMSPoint;
          Exit;
        end;
      end;


    end;
    //================================~Fin~=========================================
    //================================~GraphicLoop~=================================
    procedure GraphicLoop
    begin
    {
      //Chicken Loop *START*
      if(Chicken.Find('Chicken'))then
      begin

        //Get Chicken's Location
        ChickenPoint := Chicken.GetMSPoint;
    }

        //Check if Chicken is within smart window Bounds
        if(ChickenPoint.x > 0) and (chickenPoint.x < smartWidth)
        and(ChickenPoint.y > 0) and (chickenPoint.y < smartHeight) then

        begin
          Reflect.Smart.Graphics.Clear;
          Reflect.Smart.Graphics.DrawBox(5,5,ChickenPoint.x,ChickenPoint.y,false);
          Reflect.Smart.Graphics.DrawClippedText('Chicken','SmallChars',ChickenPoint);
        end;
      //Chicken Loop *FINISH*




    end;
    //================================~Fin~=========================================
    //============================AI Input Loop=====================================
    procedure AiInputLoop
    begin

      if not(MyPlayer.IsUnderAttack) and (InteractingName = '')
      and not (Chicken.IsUnderAttack) then // and not(MyPlayer.IsAnimating)  then
      begin
              Reflect.Mouse.Move(ChickenPoint,2,2);
              Reflect.Mouse.Click(1);
      end;






    end;
    //================================~Fin~=========================================
    //===========================~***MAIN_START***~=================================
    begin

      Reflect.Setup;
      MyPlayer.UserName := '*************';
      MyPlayer.Password := '*************';
      MyPlayer.Active := true;
      MyPlayer.Login;

      repeat
        LogicLoop;
        GraphicLoop;
        AiInputLoop;
      until(false);






    end.
    //===========================~***MAIN_FIN***~===================================
    //============================================================================//
    //============================================================================//
    //============================================================================//
    //============================================================================//
    Last edited by thatOneGuyWithTheFace; 08-28-2015 at 07:06 AM.
    THaToNeGUyWItHThEfAcE

  2. #2
    Join Date
    Aug 2007
    Posts
    539
    Mentioned
    20 Post(s)
    Quoted
    266 Post(s)

    Default

    I think the problem is here
    Simba Code:
    procedure AiInputLoop
    begin

      if not(MyPlayer.IsUnderAttack) and (InteractingName = '')
      and not (Chicken.IsUnderAttack) then // and not(MyPlayer.IsAnimating)  then
      begin
              Reflect.Mouse.Move(ChickenPoint,2,2);
              Reflect.Mouse.Click(1);
      end;
    The Chicken.IsUnderAttack seems to be checking a null npc. Which I think would crash smart.

    Take note of this;
    If you grab a npc reference via npc.get or npc.getall etc. you should grab all data needed and store into a variable. Because if you try to get an npc reference again (even different variable), if you try grab data from the first npc reference, it will crash smart.

  3. #3
    Join Date
    Jun 2014
    Location
    Lithuania
    Posts
    475
    Mentioned
    27 Post(s)
    Quoted
    200 Post(s)

    Default

    Simba Code:
    if(Npcs[i].GetName =

    Here your crash probably begins If reflection finds NO npcs then it cant access npcs[0] and crash happens, make check if length(npcs)>0 before doing this.

    Simba Code:
    if length(npcs)>0 then
    begin
    for i := 0 to High(Npcs) do
      begin
        attxp := MyPlayer.GetSkillExp(0);
        defxp := MyPlayer.GetSkillExp(1);
        strxp := MyPlayer.GetSkillExp(2);
        if(Npcs[i].GetName = 'Chicken') and not (Npcs[i].IsUnderAttack)then
        begin
          //writeln(MyPlayer.GetSkillExp(2));
          //writeln(MyPlayer.GetAnimation());
          ChickenPoint := Npcs[i].GetMSPoint;
          Exit;
        end;
      end;
    end;

    Also Ineedbot is right, and there is another issue

    Simba Code:
    procedure AiInputLoop
    begin

      if not(MyPlayer.IsUnderAttack) and (InteractingName = '')
      and not (Chicken.IsUnderAttack) then // and not(MyPlayer.IsAnimating)  then
      begin
              Reflect.Mouse.Move(ChickenPoint,2,2);
              Reflect.Mouse.Click(1);
      end;

    What if chickenpoint is out of bounds? it would crash simba too. Should check like
    Simba Code:
    if  pointInBox(inttobox(3,3,whateverx-3,whatevery-3),chickenpoint) then Reflect.Mouse.Move(ChickenPoint,2,2);

    And: what if chickenpoint.x is like 1 and it tries to draw box 5x5?. In this case it would need to draw on -4 or so it can crash too. In my eyes it should look like this:

    Simba Code:
    if(ChickenPoint.x > 5) and (chickenPoint.x < (smartWidth-5))
        and(ChickenPoint.y > 5) and (chickenPoint.y < (smartHeight-5)) then

        begin
          Reflect.Smart.Graphics.Clear;
          Reflect.Smart.Graphics.DrawBox(5,5,ChickenPoint.x,ChickenPoint.y,false);
          Reflect.Smart.Graphics.DrawClippedText('Chicken','SmallChars',ChickenPoint);
        end;

    By the way what type of crash do you get? Out of bounds? Color? Acces violation?

  4. #4
    Join Date
    Aug 2015
    Posts
    12
    Mentioned
    0 Post(s)
    Quoted
    5 Post(s)

    Default

    Thanks cosmasjdz! I'm almost sure you just pointed out the problem... when I isolated that for loop the crash persisted... going to try that that that fix now
    As for the out of bounds crash... I encountered that alot earlier and added a failsafe.(it might be a bit obscure or commented out in the code I posted) good eye though.

    As for the Crash report: there is none... simba keeps running but Smart shuts down.

    Something to Note About writeln(interactingnpc);
    returns '' when I log in
    returns 'Chicken' as soon as I attack a chicken
    returns 'Tool Leprechaun' when smart crashes <<< this only happens when the for loop is included in the code... at least as far as I've tested...
    Last edited by thatOneGuyWithTheFace; 08-28-2015 at 07:50 AM.
    THaToNeGUyWItHThEfAcE

  5. #5
    Join Date
    Jun 2014
    Location
    Lithuania
    Posts
    475
    Mentioned
    27 Post(s)
    Quoted
    200 Post(s)

    Default

    your mainloop may be tooagressive. I have had random crashed like that cause of excessive looping, add some waits

    repeat
    LogicLoop;
    wait(10);
    GraphicLoop;
    wait(10);
    AiInputLoop;
    wait(10);
    until(false);

    About leprechaun, interesting one, but personally i dont use names, i just use ids instead and no problems.

  6. #6
    Join Date
    Aug 2007
    Posts
    539
    Mentioned
    20 Post(s)
    Quoted
    266 Post(s)

    Default

    It crashes SMART because its trying to access something null'd in reflection. Its how the memory management works with the include.

    You gotta use the npc.getName, npc.getID, etc all you can before you call npc.get, npc.getall once more. Because if you try to access the 'outdated' npc, it will crash.

    The problem isn't aggressive threading. It shouldn't crash because of it.

  7. #7
    Join Date
    Jun 2014
    Location
    Lithuania
    Posts
    475
    Mentioned
    27 Post(s)
    Quoted
    200 Post(s)

    Default

    Just maybe:

    Simba Code:
    InteractingNpc: TReflectNpc;
    NullNpc: TReflectNpc;
    InteractingName: String;
    i,defxp,strxp,attxp: Integer;

    //================================~LogicLoop~===================================
    procedure LogicLoop
    begin
      Npcs.GetAll;
      Npcs.Sort;

      // code for checking if the npc is null
      InteractingNpc := NullNpc;  //assigning value between 2 treflectnpc, why? Maybe assigns nonexisting npc here or whatever?
      MyPlayer.GetInteractingNpc(InteractingNpc);
      InteractingName := InteractingNpc.GetName();
      writeln(interactingnpc);

    atleast for me it looks strange approach

  8. #8
    Join Date
    Aug 2015
    Posts
    12
    Mentioned
    0 Post(s)
    Quoted
    5 Post(s)

    Default

    Anyone know how to reset a TReflectNpc to null/its original state? ...After much digging I found this....Reflect.Smart.IsNull(InteractingNpc.Refere nce) still have problems though.


    Simplified the Code to isolate the problem:
    Simba Code:
    begin
      Npcs.GetAll;
      Npcs.Sort;

      MyPlayer.GetInteractingNpc(InteractingNpc);

      if(Reflect.Smart.IsNull(InteractingNpc.Reference))then
      begin
        writeln('nullNpc');
      end;
      if(Reflect.Smart.IsNull(InteractingNpc.Reference))then
      begin
        writeln(InteractingNpc.GetName);
        // InteractingNpc.reference = null; // this "should" work but also ends up crashing the program...
        // the problem comes here where I want to completely destroy/reset/null  InteractingNpc...
        // if I dont then InteractingNpc will remain with a grabage pointer and attempts to be accessed...
        // which ends up crashing the program
      end;
    Last edited by thatOneGuyWithTheFace; 08-28-2015 at 09:12 AM.
    THaToNeGUyWItHThEfAcE

  9. #9
    Join Date
    Aug 2015
    Posts
    12
    Mentioned
    0 Post(s)
    Quoted
    5 Post(s)

    Default

    ================================================== ===========[SOLUTION]================================================== ================================================== ===============================================




    SHORT STORY : Below is some code that returns the string of the current npc you are interacting with. (using the reflection library)

    LONG STORY : I basically had to dredge through some trial and error... and alot of searching through the reflection library...
    I ended up writing my own deconstructor for the TReflectNpc variable (for some reason this doesnt already exist in the standard reflection library).
    ... The result is a function you can put in a repeat while false loop and it gives you the string of the npc you're interacting with!!! Oh and did I mention it doesn't crash? (also no random tool leperchauns lol)

    Simba Code:
    program new;
    {$DEFINE SMART}
    {$i Reflection/Reflection.simba}

    var
    xOffset,yOffset: integer;
    ChickenBox: TBox;
    MyPlayer: TReflectLocalPlayer;
    Chicken: TReflectNpc;
    ChickenPoint: TPoint;
    Players: TReflectPlayerArray;
    smartWidth := 765;
    smartHeight := 502;
    Npcs: TReflectNpcArray;
    InteractingNpc: TReflectNpc;
    NullNpc: TReflectNpc;
    InteractingName: String;
    i,defxp,strxp,attxp: Integer;
    //================================~LogicLoop~===================================
    procedure LogicLoop
    begin
      Npcs.GetAll;
      Npcs.Sort;

      // finds chickens near the player
      //if (length(Npcs) > 0) then
      //begin
        for i := 0 to High(Npcs) do
        begin
          if(Npcs[i].GetName = 'Chicken') and not (Npcs[i].IsUnderAttack)then
          begin
            writeln('still checkin for chicken');
            ChickenPoint := Npcs[i].GetMSPoint;
            Exit;
          end;
        end;
      //end;











    //===========================Working Code Starts Here=========================================



      // sets 'InteractingNpc' to reference the npc that the player is interacting with
      MyPlayer.GetInteractingNpc(InteractingNpc);

      if(Reflect.Smart.IsNull(InteractingNpc.Reference))then // checks if InteractingNpc is null
      begin
         writeln('nullNpc'); // for debuging
        InteractingName := ''; // set name to null
      end;



      if not(Reflect.Smart.IsNull(InteractingNpc.Reference))then // checks if InteractingNpc is not null
      begin
         writeln(InteractingNpc.GetName); // shows you the name in debug window
        InteractingName := InteractingNpc.GetName; // stores it in a string

        // Deconstructing the InteractingNpc variable
        InteractingNpc._Tile := Point(0,0); // then deconstructs the npc variable so it cant be accessed
        InteractingNpc._Index := 0;
        InteractingNpc._DefReference := 0;
        InteractingNpc.reference := 0;
        // Deconstructing complete

      end;



    //==============================Working Code Ends Here==========================







    end;
    //================================~Fin~=========================================
    //================================~GraphicLoop~=================================
    procedure GraphicLoop
    begin

        // if the x and y are within the client's bounds
        if(ChickenPoint.x > 0) and (chickenPoint.x < smartWidth)
        and(ChickenPoint.y > 0) and (chickenPoint.y < smartHeight) then

        // then clear the last drawn objects... and draw the new ones.
        begin
          Reflect.Smart.Graphics.Clear;
          Reflect.Smart.Graphics.DrawBox(5,5,ChickenPoint.x,ChickenPoint.y,false);
          Reflect.Smart.Graphics.DrawClippedText('Chicken','SmallChars',ChickenPoint);
        end;




    end;
    //================================~Fin~=========================================
    //============================AI Input Loop=====================================
    procedure AiInputLoop
    begin
      {
      if not(MyPlayer.IsUnderAttack) and (InteractingName = '')
      and not (Chicken.IsUnderAttack) then // and not(MyPlayer.IsAnimating)  then
      begin
              Reflect.Mouse.Move(ChickenPoint,2,2);
              Reflect.Mouse.Click(1);
      end;
      }







    end;
    //================================~Fin~=========================================
    //===========================~***MAIN_START***~=================================
    begin

      Reflect.Setup;
      MyPlayer.UserName := '***********';
      MyPlayer.Password := '***********';
      MyPlayer.Active := true;
      MyPlayer.Login;

      repeat
        LogicLoop;
        //GraphicLoop;
        //AiInputLoop;
      until(false);






    end.
    //===========================~***MAIN_FIN***~===================================
    //============================================================================//
    //============================================================================//
    //============================================================================//
    //============================================================================//

    I posted because I know some people are going to come to this thread looking for the solution... happy Friday everyone
    Have to go to work... will clean up and make it more readable /functional when I get back
    Last edited by thatOneGuyWithTheFace; 08-28-2015 at 11:00 AM.
    THaToNeGUyWItHThEfAcE

  10. #10
    Join Date
    Feb 2013
    Location
    Rimmington
    Posts
    319
    Mentioned
    33 Post(s)
    Quoted
    183 Post(s)

    Default

    Quote Originally Posted by thatOneGuyWithTheFace View Post
    ================================================== ===========[SOLUTION]================================================== ================================================== ===============================================




    SHORT STORY : Below is some code that returns the string of the current npc you are interacting with. (using the reflection library)

    LONG STORY : I basically had to dredge through some trial and error... and alot of searching through the reflection library...
    I ended up writing my own deconstructor for the TReflectNpc variable (for some reason this doesnt already exist in the standard reflection library).
    ... The result is a function you can put in a repeat while false loop and it gives you the string of the npc you're interacting with!!! Oh and did I mention it doesn't crash? (also no random tool leperchauns lol)

    Simba Code:
    program new;
    {$DEFINE SMART}
    {$i Reflection/Reflection.simba}

    var
    xOffset,yOffset: integer;
    ChickenBox: TBox;
    MyPlayer: TReflectLocalPlayer;
    Chicken: TReflectNpc;
    ChickenPoint: TPoint;
    Players: TReflectPlayerArray;
    smartWidth := 765;
    smartHeight := 502;
    Npcs: TReflectNpcArray;
    InteractingNpc: TReflectNpc;
    NullNpc: TReflectNpc;
    InteractingName: String;
    i,defxp,strxp,attxp: Integer;
    //================================~LogicLoop~===================================
    procedure LogicLoop
    begin
      Npcs.GetAll;
      Npcs.Sort;

      // finds chickens near the player
      //if (length(Npcs) > 0) then
      //begin
        for i := 0 to High(Npcs) do
        begin
          if(Npcs[i].GetName = 'Chicken') and not (Npcs[i].IsUnderAttack)then
          begin
            writeln('still checkin for chicken');
            ChickenPoint := Npcs[i].GetMSPoint;
            Exit;
          end;
        end;
      //end;











    //===========================Working Code Starts Here=========================================



      // sets 'InteractingNpc' to reference the npc that the player is interacting with
      MyPlayer.GetInteractingNpc(InteractingNpc);

      if(Reflect.Smart.IsNull(InteractingNpc.Reference))then // checks if InteractingNpc is null
      begin
         writeln('nullNpc'); // for debuging
        InteractingName := ''; // set name to null
      end;



      if not(Reflect.Smart.IsNull(InteractingNpc.Reference))then // checks if InteractingNpc is not null
      begin
         writeln(InteractingNpc.GetName); // shows you the name in debug window
        InteractingName := InteractingNpc.GetName; // stores it in a string

        // Deconstructing the InteractingNpc variable
        InteractingNpc._Tile := Point(0,0); // then deconstructs the npc variable so it cant be accessed
        InteractingNpc._Index := 0;
        InteractingNpc._DefReference := 0;
        InteractingNpc.reference := 0;
        // Deconstructing complete

      end;



    //==============================Working Code Ends Here==========================







    end;
    //================================~Fin~=========================================
    //================================~GraphicLoop~=================================
    procedure GraphicLoop
    begin

        // if the x and y are within the client's bounds
        if(ChickenPoint.x > 0) and (chickenPoint.x < smartWidth)
        and(ChickenPoint.y > 0) and (chickenPoint.y < smartHeight) then

        // then clear the last drawn objects... and draw the new ones.
        begin
          Reflect.Smart.Graphics.Clear;
          Reflect.Smart.Graphics.DrawBox(5,5,ChickenPoint.x,ChickenPoint.y,false);
          Reflect.Smart.Graphics.DrawClippedText('Chicken','SmallChars',ChickenPoint);
        end;




    end;
    //================================~Fin~=========================================
    //============================AI Input Loop=====================================
    procedure AiInputLoop
    begin
      {
      if not(MyPlayer.IsUnderAttack) and (InteractingName = '')
      and not (Chicken.IsUnderAttack) then // and not(MyPlayer.IsAnimating)  then
      begin
              Reflect.Mouse.Move(ChickenPoint,2,2);
              Reflect.Mouse.Click(1);
      end;
      }







    end;
    //================================~Fin~=========================================
    //===========================~***MAIN_START***~=================================
    begin

      Reflect.Setup;
      MyPlayer.UserName := '***********';
      MyPlayer.Password := '***********';
      MyPlayer.Active := true;
      MyPlayer.Login;

      repeat
        LogicLoop;
        //GraphicLoop;
        //AiInputLoop;
      until(false);






    end.
    //===========================~***MAIN_FIN***~===================================
    //============================================================================//
    //============================================================================//
    //============================================================================//
    //============================================================================//

    I posted because I know some people are going to come to this thread looking for the solution... happy Friday everyone
    Have to go to work... will clean up and make it more readable /functional when I get back
    It crashes because you cluster up the memory. You can't use a NPC variable within two functions at once as it'll cluster it up when you use .Get functions. If you don't believe me I can show you parts of my Zulrah script, it does not crash





  11. #11
    Join Date
    Oct 2006
    Posts
    6,752
    Mentioned
    95 Post(s)
    Quoted
    532 Post(s)

    Default

    Quote Originally Posted by thatOneGuyWithTheFace View Post
    ....
    Well, I'll give you credit for definitely trying!
    But it seems as if you're missing a few points with reflection, and how the include handles it.. This is a short snip of what you are trying to do:

    Simba Code:
    program Example;
    {$DEFINE SMART}
    {$i Reflection/Reflection.simba}


    var
      LocPlayer: TReflectLocalPlayer;
      InteractingNpc: TReflectNpc;

    begin
      Reflect.Setup;
      LocPlayer.Create;
      repeat
      if LocPlayer.GetInteractingIndex <> -1 then //then we are interacting
      begin
        LocPlayer.GetInteractingNpc(InteractingNpc); //Grab what we are interacting
        WriteLn(InteractingNpc.GetName);
      end;
      Wait(200);
      until(False);
    end.

    You don't have to "deconstruct" anything, which BTW setting everything to 0 isn't deconstructing anything and will actually cause it to crash later because you're setting both reference pointers to 0, which when the include tries to free them later on, will not work as 0 is undefined in memory. What the others were saying about how it crashes is this:

    Simba Code:
    program Example;
    {$DEFINE SMART}
    {$i Reflection/Reflection.simba}


    var
      LocPlayer: TReflectLocalPlayer;
      Npc1, Npc2: TReflectNpc;
      Temp: string;

    begin
      Reflect.Setup;
      LocPlayer.Create;

      Npc1.Find('Guard');
      Temp := Npc1.GetName;
      Npc2.Find('Banker'); //This Free's Npc1, you can NOT access Npc1 now

      WriteLn(Npc1.GetName); //Will eventually crash SMART
      WriteLn(Npc2.GetName); //Totally fine
      WriteLn(Temp); //Fine as well ofc..
    end.

    This is of course a negative about the way the include is set up, but it was either this, or have NO internal freeing of memory and rely on the scripter for that, but that would cause massive memory leaks all too often.

    This is why java and other languages are much better for this type of stuff, since they have built in destructors that will be called whenever you leave the scope of the variable, so you don't ever have to worry about freeing anything.
    “The long-lived and those who will die soonest lose the same thing. The present is all that they can give up, since that is all you have, and what you do not have, you cannot lose.” - Marcus Aurelius

  12. #12
    Join Date
    Aug 2015
    Posts
    12
    Mentioned
    0 Post(s)
    Quoted
    5 Post(s)

    Default

    Quote Originally Posted by elfyyy View Post

    You don't have to "deconstruct" anything, which BTW setting everything to 0 isn't deconstructing anything and will actually cause it to crash later because you're setting both reference pointers to 0, which when the include tries to free them later on, will not work as 0 is undefined in memory. What the others were saying about how it crashes is this:
    Hey. On lunch break here.
    Argh... I can't believe I didn't think to look at LocalPlayer.GetInteractingIndex when I was going through the include! Must've not had enough sleep haha. Anyways, thank you so much for all the replies...So Great. I didn't expect so many. I think this will definitely help any fellow script-noobs trying their hand at reflection as well... @Elfyyy For that well worded, straight to the point, useful explanation... thank you. Also apologies for under-estimating the completeness of the reflection library. Some false assumptions were made there. Again, To Elfyyy and everyone who replied...this saved me hours of of future bugs and debugging. Thanks!
    Last edited by thatOneGuyWithTheFace; 08-28-2015 at 04:32 PM.
    THaToNeGUyWItHThEfAcE

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •