Couple Problems

Discussion in 'Programming' started by Ted Gress, Mar 31, 2019.

  1. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    First off I promise not to post again until these issues are resolved. :)

    This is the code for my collision between my bats and my brains. What I want it to do is the following. The player controlling the bats double clicks on a brain when it is next to it. The brain begins its attack animation and so does the bat. The player keeps clicking on the brain, which causes a "thumping" sound and causes damage indicators to float upward from the brain. There is a damage meter below the bat and as the player takes damage, the meter empties. If the player wants to, he/she can click away from the brain and run to escape (that's in another posting). So the brain (hopefully) gets killed by the bat and then the bat is free to fly around until it runs into another brain.

    This is what is happening. The player double clicks on the brain. After a couple clicks the brain starts taking damage and the bat starts its flying animation. Then every click that "hits or does damage" changes the brain object's sprite to the attack sprite for the bat for some reason. As the player clicks on the brain, every hit makes a thumping sound and the damage indicator works as it should. The same for the damage meter. If was player wants to click away from the brain to get away, sometimes it will back up (assuming you are escaping to the rear) and the brain will follow, sometimes it won't do anything. So then the brain gets killed by the bat and then the bat is free to fly around until it runs into another brain.

    Phew

    Ok. To start, here is the code for collision:
    Code:
    var play_timer = 0;
    var played = true;
    
    var colliderbrain;
    var colliderbat;
    
    
    global.timer_big_brain--;
    if (global.timer_big_brain <= 0)
    {
        global.timer_big_brain = room_speed/8;
    
        if (mouse_check_button_released(mb_left))
        {
            show_debug_message("LMB pressed");
       
       
            colliderbrain = instance_position(mouse_x, mouse_y, SimpleBrain);
           
           
            if (instance_exists(colliderbrain))
            {
                show_debug_message("Collider brain exists");
            }
           
       
            if (colliderbrain != noone)
            {
                show_debug_message("Collider Brain initializating collider bat");
                with (colliderbrain)
                {
                    show_debug_message("With Colliderbrain");
                    colliderbat = instance_position(mouse_x, mouse_y, other)
                }
            }
       
            /////////////////////////COLLIDERBRAIN AND COLLIDER BAT//////////////////////
           
            if (colliderbrain == noone || colliderbat == noone)
            {
                return;
            }
       
            //////////////////////////////////////////////
           
            show_debug_message(object_get_name(colliderbrain) + "shoujld be a brain");
            show_debug_message(object_get_name(colliderbat) + "should be a bat");
           
            ///////////////////////////////////////
       
            //colliderbat = other;//instance_place(mouse_x, mouse_y, SentryBatObject)
            if (colliderbrain != noone)
            {
    
                show_debug_message("Collider brain is not noone");
                with (colliderbrain)
                {
           
                //    if (point_distance(argument0, argument1, x, y) < 40)
                    if (point_distance(argument0, argument1, x, y) < 100)
                    {
    
                        ///colliderbrain is Brain
                        show_debug_message("With colliderbrain");
           
                   
                        sprite_index = SimpleBrainAttack;
               
                        hp_minus = irandom_range(10, 30)
                        hp = hp - hp_minus;
           
                        speed =0;
                        under_attack = true;
                        took_a_hit = true;
                        //sprite_index = SentryBatAttack
                        //image_speed = 1;
                        audio_play_sound(BatThumpSound,20,false);
                   
                        show_debug_message("Showing Damage Indicator");
                        floater = instance_create_depth(x+10, y-10, -17000, DamageIndicatorObject);
                        floater.text = string(hp_minus);
                   
                       
                   
                        //killl the brain  
                        if (hp <= 0)
                        {
                            show_debug_message("Kill the brain");
                       
                            global.achievement_gold_counter++;
                            global.achievement_tome_experience += 20;
                            show_debug_message("Dead Brain Ghost and Fading Gem");
                            audio_play_sound(DieingBrainSound, 20, false);
                            instance_create_depth(x, y, -1100,DeadBrainObject);      
                            instance_create_depth(x-150, y-20, -1100, FadingGemObject);
               
                            instance_destroy();
                        }
                    }      
           
                }
            }
       
                if (colliderbat != noone)
                {
                    with (colliderbat)
                    {
                        show_debug_message("Colliderbat is not noone");
           
                        //damage to batq
                        if (!global.group_invincibility)
                        {
                            hp = hp - 1;
                            damage = 1;
                            damage_dealt_to_bat = damage;
                        }
       
                       
                       
                        sprite_index = SentryBatAttack;
                        image_speed = 0;
                        show_debug_message("SentryBatAttack");
                       
       
                        //alarm[5] = room_speed;
               
                        under_attack = true;  
                        took_a_hit = true;
                        //sprite_index = SimpleBrainAttack;
                        //audio_stop_sound(BatWingsMovementSound);
           
                        /* kill the bat */
           
                        if (hp <= 0)
                        {
                            audio_play_sound(BatDeathSound, 20, false);
                            instance_create_depth(x, y, -1100,DeadBatObject);
                            global.num_sentry_killed++;
                            instance_destroy();
                           
               
                        }
                    }
                }    
    I hope this makes sense. colliderbat is the bat you control in the game in this collision. You can have control of multiple different kinds of bats. colliderbrain is is the brain the AI controls in this collision.

    Screenshot 1 - sentry bat graphic responding the attacking brain when the sentry bat is attacking the brain
    Screenshot 2 - the way the brain should look

    Sorry about the long post but I wanted to be thorough
     

    Attached Files:

  2. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    Okay Ted, do yourself a favor, and I mean this in a considerate way. since that block of code is now for the time being backed up here on the forum, rewrite that entire script and your project. And as you are doing that, remove any debugging lines, like all those show_debug_message(), remove all the lines that you have commented out unless you think they are the right line. Rewrite your code with only comments to remind you what a particular block of code is supposed to be doing if you need to. Furthermore as you are rewriting that code, look at it and think to yourself, "Are there any blocks of code that I can combine together? Are there any redundancies I can get rid of?" Here's one redundancy you can get rid of: checking if an instance exist AND checking if that instance is not noone. there are situations where those two conditions are separate, but this is not one of them. If the incense does not exist, then the variable is for sure noone.

    Don't you have your code rewritten, condensed down, cleaned up, and all that jazz, test it. See if it works. If it doesn't work, do not try to debug it by adding stuff, since clearly that is not helping you out very well.

    From that code, it does look like the brain should be using the brain's Sprite, and the bat should be using the bat Sprite, at least to me. Which would suggest that the variables are holding the wrong values or you're withare not set right. But cleaning up your code should help with that.

    What are the arguments that you are passing through this script? Obviously they are coordinates, but the coordinates of what?
     
    Last edited: Apr 3, 2019
  3. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    No.I put way too much work into this. Rewriting the collision script is plausible. Rewriting my entire project because of a small part of it is outrageous.

    They are using brain's sprite for brain and bat's sprite for bat. That code does not cleaned up.
    The coordinates are the x and y of the brain enemy in the collision.
    SimpleBrainSentryBatCollision(x,y);

    Oh and way to discourage and put somebody down.

    I mean.....do you understand how hard it is to develop a game of this scope by yourself. Seriously, it is me and an artist. Yes if I could do it over again I wouldn't have made something so complex, but I already dove into It and not finishing It up (which I am doing ) I don't think worth wasting all of the hours put into it.
     
  4. BaBiA Game Studio

    BaBiA Game Studio Member

    Joined:
    Jun 20, 2016
    Posts:
    754
    A lot of us understand exactly this, if not more (where we are the only person working on our projects, not even with any artist). I don't think @TheouAegis is saying scrap and start from scratch again, but take out all the bits that are no longer required, ie: the debugging statements, so that the code is clean and can be clearly understood rather than loads of extraneous lines of commented code that may or may not have anything to do with the project any more.

    You're also not the only one who has had to scrap a project and start again because of issues that came down to coding problems/mistakes. I have rewritten chunks of projects repeatedly because of these, and each iteration it gets better and better.
     
    Bentley and Taddio like this.
  5. Taddio

    Taddio Member

    Joined:
    Nov 16, 2018
    Posts:
    421
    Well, see the bright side of it. Maybe this time you are hacking through a jungle with a butter knife, I am sure next time around you will:
    - use parenting
    - name your variables in a meaningful, short and distinguishable way
    - use the correct variables scopes
    - bring a machete to hack aformentionnrd jungle.

    And, I'm preeeeeeetty sure @TheouAegis knows perfectly what it's like to develop a game of this scope ;)

    Hang in there brother, I promise I'll try it when it's done :)
     
  6. rIKmAN

    rIKmAN Member

    Joined:
    Sep 6, 2016
    Posts:
    3,793
    Seems to me like you are spreading yourself too thin.
    When I checked the forum yesterday or the day before 6 of the first 10 threads on the "New Posts" page were by you.

    Try to concentrate on one problem at a time and give it your full attention until you manage to solve it rather than jumping between multiple problems and trying to solve them all at the same time whilst not really focusing yourself 100% on any of them.

    I'd also agree with the Theou and BaBiA that it would help you massively to spend a day to clean up your project and code, remove anything that is no longer needed / valid and comment it in a way that makes it clear to you what each piece of code is supposed to do and that help might provide some clarity when stepping through it logically to find any issues.

    It can also be beneficial to take a break if you start to get too frustrated with things - sometimes the answer to a problem or a new way to approach a problem will come to mind when you least expect it.
     
    Last edited: Apr 3, 2019
  7. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    I'm not redoing it. I have over a year of code and it is almost finished. I have five bugs that need to be fixed, the IAP, and the code-side is about complete.They are the same bugs I've been posting about. Note I haven't been coming up with new errors I need help with on the forum. It is the same frickin problems. I understand from your perspective it is limited, you don't know the scope of the game, what's done, what isn't done, the game mechanics, the gameplay, etc. If you looked from my perspective I see a project 80% done, a few bugs that are really tough to fix, and a game that with at most another month of coding and art will be ready for beta. I can detail what is done so far and what has to be done yet but I shouldn't have to.

    @rIKmAN Agreed. I should take a day to do cleanup. Good idea. I've been putting it off.
     
    rIKmAN likes this.
  8. rIKmAN

    rIKmAN Member

    Joined:
    Sep 6, 2016
    Posts:
    3,793
    I didn't tell you to redo it, I told you to take a breath, clean up the project and then attack one problem at a time rather than trying to fix six at once.
    Based off your threads on here you have tied yourself in a few knots and cleaning up the project would help you be able to identify the cause of the issues.

    Take the advice or don't, you do you - no need to get defensive.

    edit: Seems you weren't replying to me, but without you quoting anyone it seemed you were.
     
  9. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    @rIKmAN Agreed. Let's end this terrible thread. I don't have anything else to say.
     
  10. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    My phone added "and" when i said "in your project." Although cleaning up the rest of your project would still be a good idea, it's just the problem areas that really need focus right now.

    And cleaning up problem areas will likely reveal what's causing those bugs. I wasn't even saying back in the battimer threas to rewrite your whole project with arrays so that your bat code is actually sensible, I'm just saying if you had learned to use arrays early on, many of these issues would be nonexistent.

    And I think I just found your issue in this code.

    That was the issue you claimed in your first post. Hence why I said it LOOKED like the right instances should be changing to the right sprite, but they aren't -- according to you.

    Code:
    if (mouse_check_button_released(mb_left))
       {
              colliderbrain = instance_position(mouse_x, mouse_y, SimpleBrain);
       
           if (colliderbrain != noone)
           {
               with (colliderbrain)
               {
                   colliderbat = instance_position(mouse_x, mouse_y, other)
               }
           }
    
    What is at mouse_x and mouse_y? A brain. Unless the bat and brain are overlapping at the exact point that the player clicks, only colliderbrain would get set. Since you already know colliderbrain isn't noone, the with is unnecessary. On the other hand, it would make sense if you had
    Code:
     with colliderbrain {
        colliderbat = instance_place(x,y,other);
    }
    And then there may be an issue with other. Who os calling that script? Every bat or every brain? If arguments 0 and 1 are the x,y of a brain, then whybare you checking for a brain at the mouse if you are already passing the brain's coordinates?

    BUT IF the script is run FROM A BRAIN's SCOPE, then colliderbrain and colliderbat would be the same instance and that would explain the brain using the bat's attack sprite.
     
  11. Bentley

    Bentley Member

    Joined:
    Jun 18, 2017
    Posts:
    654
    Yeah man, I downloaded @TheouAegis 's Castlevania remake. I learned a lot.
     
  12. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    Castlevania remake? @TheouAegis is now my favorite person in the world. Where can I get my hands on it?

    back to the code

    You say use arrays. How should I be using them....I don't follow
     
  13. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    I'm not following you.

    Code:
    colliderbrain = instance_position(mouse_x, mouse_y, SimpleBrain);
    Is this code t he code you are referring to?
    The x,y passed in are the coordinates from a brain object. So the instance_position is to get the instance of a SimpleBrain (colliderbrain). I'm sure there is a better way, I just don't know it.

    Code:
    with colliderbrain {
        colliderbat = instance_place(x,y,other);
    }
    I don't know how to get the bat instance in the collision. I'm used to using the event menus. That's the core of it.
    I need to get at the colliderbat object. I thought using instance_position with the coordinates of the brain and using other but
    now that I look at it it obviously won't work. So the question is, if you have two objects you want to script a collision for, and you have an instance for one, how the heck do you get the instance for the other object in the collision??
     
  14. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    What I'm saying with the mouse is your code says get the brain that the mouse is clicking on, then it goes on to say if it got a brain, get the bat that the mouse is clicking on. The only way that's ever going to happen is if where the mouse is at there is a brain pixel overlapping with a bat pixel. Which is possible, but not always going to be likely. So if a brain is clicked on, then it will look for a bat at the exacte same mouse coordinate, which there probably won't be in most cases. If you click on a bat first then there likely won't be a brain there, so colliderbrain is set to noone and colliderbat never gets set. It's just an issue with using instance_position(mouse_x, mouse_y,obj).

    you already have access to the x & y coordinates of the brain instance once you get its ID in colliderbrain..there is no need to pass arguments in that script.

    and then even if you did get the x & y coordinates of the brain that is underneath the mouse and passed those coordinates to that script, your script is saying check the distance between that brain's x & y coordinates to its own x & y coordinates, then. That's going to make it so the bat attacks too soon.

    I have to go shower now.

    UPDATE

    Begin a brain ideas not your issue, it's getting an ID.But getting the ID of the bat or bats is the issue.if I remember right about your project, don't you have bats that are ranged attackers? In other words, a bat that spits fire or attached with sound waves? in that case, you wouldn't want to find the bat that is actually on top of the brain, you'd want to find the bat that is an attack range. and are you limiting it to just one bat attacking one brain, or do you want all bats that are within range to attack the brain? And either case, once you have your brain, you are going to need to use a with(objSimpleBat) or whatever your bat parent is called 2 1st loop through every single batt on the screen and find the one that is actually within attacking range. Then that bat would be colliderbat.

    and in any case, this code would be run from your controller object, since it would be affecting all brains and it would be affecting all bats. He will not be passing any arguments to it whatsoever, because there is nothing that you would need to pass to the script that you cannot find out inside the script itself.

    Time for work.
     
    Last edited: Apr 3, 2019
  15. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    Yeah you are right about my project. I have bats whose attacks are projectiles. One that shoots sonic waves, one that throws snowballs, etc. So I guess it is a matter of finding which bats are in attack range for the appropriate bat. I want to be able to select which brain is being attacked by selecting a bat to be the selected bat by clicking on it and then clicking on the brain to attack. So I would iterate through the bat objects, for each bat check distance_to_pointt for all brains and if its say, the sentry bat, that is essentially a pawn and only attacks what's adjacent, .the sentry brain attacks the brain.

    So:
    1. Left Mouse Click
    2. Loop through Bats
    3 For each Brain check distance to point
    4. If the range for the bat is less than or equal to check distance to point
    5. Attack Brain with Bat

    Does this sound reasonable?
     
  16. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    Something like (again, not sure what objects are your parents, so i'll use objBigBrain and objSimpleBat)
    Code:
    if mouse_check_button_pressed(mb_left) {
       var n = instance_position(mouse_x,mouse_y, all);
       if n == noone {    //Check if the player is cancelling the attack
          colliderbrain = noone;
          if colliderbat != noone
             colliderbat.attackTarget = noone;    //Tell the currently selected bat to stop focusing a brain (optional)
          colliderbat = noone;    //Neither variable is temporary now, they're local to the controller object
          return 0;   //No point continuing with the script if nothing was clicked on
       }
       if n.object_index == objBigBrain || object_get_parent(n.object_index)==objBigBrain 
       {
          colliderbrain = n;
          colliderbat = noone;    //This may not work for you, but it would force the player to pick a new bat after clicking on a brain
       }
       if n.object_index == objSimpleBat || object_get_parent(n.object_index)==objSimpleBat
          colliderbat = n;
    }
    
    //Now that we may have established a brain-bat pairing, we can move on
    if !colliderbrain || !colliderbat return 0;    //If either target hasn't been chosen, end the script for now
    
    with colliderbat
       attackTarget = colliderbrain;  
    
    with colliderbrain 
       if attackTarget == noone
          attackTarget = colliderbat;
       else
       if distance_to_object(attackTarget) > attackRange
          attackTarget = colliderbat;
    
    colliderbrain = noone;
    colliderbat = noone;
    
    So your bats and brains would have a variable attackRange, which is how close they need to be to the target before engaging in combat. For ranged bats (or brains), this would be higher than for melee bats and brains. The target of each unit's attacks (to determine which one will take damage and where the projectiles will fly to) will be saved in the variables attackTarget that you'd give to all bats and brains.

    Your bats would have in their Step Event something like
    Code:
    if attackTarget != noone {
       if distance_to_object(attackTarget) > attackRange
          move_toward_point(attackTarget.x,attackTarget.y, flyspeed);
       else
       {
          speed=0;
          //do your attacking stuff for the bat and deal damage to attackTarget
       }
    }
    For the brains, you could either have it move toward its attackTarget, or you could have it continue toward the castle if attackTarget is out of range. Otherwise, it's code would be similar. Have it attack when it's in range and deal its damage to the target bat.

    With a structure like this, you'd be able to have multiple bats of different abilities attacking multiple brains. You could even have multiple bats attacking the same brain, or multiple brains attacking the same bat (if you wanted).

    I left out the bit about setting attackTarget to noone in either case. Typically that would only happen when attackTarget finally dies.
     
  17. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    @TheouAegis Awesome! Couple quick questions. How do I set the variable attackTarget. By that what I mean you have attackTarget.x and attackTarget.y. Same thing with n.object_index.
    Another example:
    Code:
    var n = instance_position(mouse_x,mouse_y, all);
    Is n.object_index built into the instance_position variable return? Also how is "all" used in this case?

    For
    Code:
     if n == noone {    //Check if the player is cancelling the attack
    That's if the player clicks off of the bats/brains right? It is if the click off on the grass to escape?

    Code:
    colliderbat = noone;    //This may not work for you, but it would force the player to pick a new bat after clicking on a brain
       }
    Why does this force t he player to pick a new bat?

    Finally, this is all occuring in my script. Correct? Then the step event is where I actually do the movements?

    Oh and I want your castlevania remake. I will pay for it.
     
  18. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    In the Create events of brains and bats, default attackTarget to noone.

    In the script that handles pairing up targets, as soon as colliderbrain and collider bat are both set, it assigns their ids to each other's attackTarget.

    n is to see if the player clicked on anything; it's the id if whatever he clicked on. But you did bring up an issue I overlooked in my code.
    Since I used instance_position(mouse_x, mouse_y, all), n could be some other non-brain or non-bat instance in the room, which wouldn't work. So...
    Code:
       var n = instance_position(mouse_x,mouse_y, all);
      
       if n.object_index == objBigBrain || object_get_parent(n.object_index)==objBigBrain
       {
         colliderbrain = n;
         colliderbat = noone;    //This may not work for you, but it would force the player to pick a new bat after clicking on a brain
       }
       else
       if n.object_index == objSimpleBat || object_get_parent(n.object_index)==objSimpleBat
         colliderbat = n;
       else {
          colliderbrain=noone;
          colliderbat=noone;
       }
    So now if n is anything OTHER THAN a brain or bat, it will deselect both bat and brain (if any selected).


    As for thtat line about picking a new bat, that's just to force the player to pick a brain first and then a bat. I don't rhink that would be a good mechanic after all, so yeah...

    Also, sincr colliderbrain and colliderbat are now instance variables in your controller, you can have the controller draw a selection marker on the brain and/or bat.
     
  19. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    Ok. I don't understand the attackTarget part. I can't do:

    with colliderbrain.attackTarget { } can I?

    Edit:

    Ok I think I coded this right but it isn't selecting the colliderbrain or colliderbat. Its acting like I'm just clicking off - not on the bat or brain.

    This is how my script is set up:

    Code:
    if mouse_check_button_pressed(mb_left) {
        show_debug_message("Mouse Check Button collision pressed");
      var n = instance_position(mouse_x,mouse_y, all);
     
       if n.object_index == BigBrainObject || object_get_parent(n.object_index)==BigBrainObject
       {
           show_debug_message("Big Brain Object is selected");
         colliderbrain = n;
         colliderbat = noone;    //This may not work for you, but it would force the player to pick a new bat after clicking on a brain
       }
       else
       if n.object_index == SentryBatObject || object_get_parent(n.object_index)==SentryBatObject {
         colliderbat = n;
         show_debug_message("Sentry Bat Object is selected");
       }
       else {
           show_debug_message("Click off of sentry bat and brain");
          colliderbrain=noone;
          colliderbat=noone;
       }
      
       with colliderbat
         attackTarget = colliderbrain; 
    
        with colliderbrain
          if attackTarget == noone
             attackTarget = colliderbat;
          else
          if distance_to_object(attackTarget) > attackRange
             attackTarget = colliderbat;
    
    }
    
    with colliderbrain
    {   
        show_debug_message("With colliderbrain");
            with attackTarget
            {
                
                //damage to batq
                if (!global.group_invincibility)
                {
                    hp = hp - 1;
                    damage = 1;
                    damage_dealt_to_bat = damage;
                }
        
            }
        
            ///colliderbrain is Brain
            show_debug_message("With colliderbrain");
            
                    
            sprite_index = SimpleBrainAttack;
            
            
            //under_attack = true;
            //took_a_hit = true;
                        //sprite_index = SentryBatAttack
                        //image_speed = 1;
            audio_play_sound(BatThumpSound,20,false);
                    
            show_debug_message("Showing Damage Indicator");
                    
                        
                    
            //killl the brain   
            if (hp <= 0)
            {
                show_debug_message("Kill the brain");
                        
                global.achievement_gold_counter++;
                global.achievement_tome_experience += 20;
                show_debug_message("Dead Brain Ghost and Fading Gem");
                audio_play_sound(DieingBrainSound, 20, false);
                instance_create_depth(x, y, -1100,DeadBrainObject);       
                instance_create_depth(x-150, y-20, -1100, FadingGemObject);
                instance_destroy();
            }
        
    }
    
    with colliderbat
    {
        sprite_index = SentryBatAttack;
        
        with attackTarget
        {
            hp_minus = irandom_range(10, 50);
            hp = hp - hp_minus;
                
        
            floater = instance_create_depth(x+10, y-10, -17000, DamageIndicatorObject);
            floater.text = string(hp_minus);
        }
            
            
        if (hp <= 0)
        {
            audio_play_sound(BatDeathSound, 20, false);
            instance_create_depth(x, y, -1100,DeadBatObject);
            global.num_sentry_killed++;
            instance_destroy();
                            
                
        }
        
    }
    And the output is just:

    "Click off of sentry bat and brain"
     
    Last edited: Apr 5, 2019
  20. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    Did you check your parenting? I mean, I tested those conditionals in gms1 before I posted them.
     
  21. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    I'm not using parenting.

    The following is the code you gave me to do the pairing:

    Code:
    if mouse_check_button_pressed(mb_left) {
        show_debug_message("Mouse Check Button collision pressed");
      var n = instance_position(mouse_x,mouse_y, all);
     
       if n.object_index == BigBrainObject || object_get_parent(n.object_index)==BigBrainObject
       {
           show_debug_message("Big Brain Object is selected");
         colliderbrain = n;
         colliderbat = noone;    //This may not work for you, but it would force the player to pick a new bat after clicking on a brain
       }
       else
       if n.object_index == SentryBatObject || object_get_parent(n.object_index)==SentryBatObject {
         colliderbat = n;
         show_debug_message("Sentry Bat Object is selected");
       }
       else {
           show_debug_message("Click off of sentry bat and brain");
          colliderbrain=noone;
          colliderbat=noone;
       }
     
       with colliderbat
         attackTarget = colliderbrain;
    
        with colliderbrain
          if attackTarget == noone
             attackTarget = colliderbat;
          else
          if distance_to_object(attackTarget) > attackRange
             attackTarget = colliderbat;
    
    }
    
    with colliderbrain
    {  
        show_debug_message("With colliderbrain");
            with attackTarget
            {
               
                //damage to batq
                if (!global.group_invincibility)
                {
                    hp = hp - 1;
                    damage = 1;
                    damage_dealt_to_bat = damage;
                }
       
            }
       
            ///colliderbrain is Brain
            show_debug_message("With colliderbrain");
           
                   
            sprite_index = SimpleBrainAttack;
           
           
            //under_attack = true;
            //took_a_hit = true;
                        //sprite_index = SentryBatAttack
                        //image_speed = 1;
            audio_play_sound(BatThumpSound,20,false);
                   
            show_debug_message("Showing Damage Indicator");
                   
                       
                   
            //killl the brain  
            if (hp <= 0)
            {
                show_debug_message("Kill the brain");
                       
                global.achievement_gold_counter++;
                global.achievement_tome_experience += 20;
                show_debug_message("Dead Brain Ghost and Fading Gem");
                audio_play_sound(DieingBrainSound, 20, false);
                instance_create_depth(x, y, -1100,DeadBrainObject);      
                instance_create_depth(x-150, y-20, -1100, FadingGemObject);
                instance_destroy();
            }
       
    }
    
    with colliderbat
    {
        sprite_index = SentryBatAttack;
       
        with attackTarget
        {
            hp_minus = irandom_range(10, 50);
            hp = hp - hp_minus;
               
       
            floater = instance_create_depth(x+10, y-10, -17000, DamageIndicatorObject);
            floater.text = string(hp_minus);
        }
           
           
        if (hp <= 0)
        {
            audio_play_sound(BatDeathSound, 20, false);
            instance_create_depth(x, y, -1100,DeadBatObject);
            global.num_sentry_killed++;
            instance_destroy();
                           
               
        }
       
    









    On a side note the step event for the bats is:

    Code:
    
    
    if (hp <= 0)
    {
        instance_destroy();
    }
    
    
    if attackTarget != noone {
       if distance_to_object(attackTarget) > attackRange
          move_towards_point(attackTarget.x,attackTarget.y, flyspeed);
       else
       {
          speed=0;
          //do your attacking stuff for the bat and deal damage to attackTarget
       }
    }
    
            if (flight == true)
            {  
               
                           
                   
               
                if (!global.acceleration)
                {
                    if (point_distance(x, y, target_placement_x-100, target_placement_y-100) > 15)
                    {
                        play_timer--;
                        if (played == false)
                        {
                            audio_play_sound(BatWingsMovementSound, 20, false);
                            played = true;
                        }
                        if (play_timer <= 0)
                        {
                            played = false;
                            play_timer = room_speed*2;
                        }
                   
                        sprite_index = SentryBatWalk;
                        move_towards_point( target_placement_x-100, target_placement_y-100, 10 );  
                        global.dropped_bat = false;
                       
                    }
                    else
                    {
                        speed = 0;
                        flight = false;
                        sprite_index = SentryBatIdle;
                    }
                }
               
                else
                {
                    if (point_distance(x, y, target_placement_x-100, target_placement_y-100) > 40)
                    {
                       
                        play_timer--;
                        if (played == false)
                        {
                            audio_play_sound(BatWingsMovementSound, 20, false);
                            played = true;
                        }
                        if (play_timer <= 0)
                        {
                            played = false;
                            play_timer = room_speed*2;
                        }
                   
                       
                                       
                        sprite_index = SentryBatWalk;
                        move_towards_point( target_placement_x-100, target_placement_y-100, 30 );  
                        global.dropped_bat = false;
                    }
                    else
                    {
                        speed = 0;
                        flight = false;
                        sprite_index = SentryBatIdle;
                    }
               
               
                }
            }
           
       
    
        //if invincible
        if (global.group_invincibility == true)
        {
            //if the cross doesn't already exist
            if (!object_exists(AlchemistInvincibleObject))
            {
                //create a cross
                inst = instance_create_depth(x+110, y+110, -1100, AlchemistInvincibleObject);
            }
            //move sentry bats along wi                  th the bat
            //cross
            with (AlchemistInvincibleObject)
            {
                x = other.x;
                y = other.y;
                move_towards_point( other.x-10, other.y-10, 10 );  
            }      
           
        }
       
    ///////////////////////ACCELERAtion///////////////
    
    //if invincible
        if (global.acceleration)
        {
            //if the cross doesn't already exist
            if (!object_exists(AccelerationBuff))
            {
                //create a lightning bolt
                inst = instance_create_depth(x+110, y+110, -1100,AccelerationBuff);
            }
            //move sentry bats along wi                  th the bat
            //cross
            with (AccelerationBuff)
            {
                //x = other.x;
                //y = other.y;
                if distance_to_point(other.x-10,other.y-10) < 20
                {
                    x = other.x-10;
                    y = other.y-10;
                    speed = 0;
                }
       
               
                move_towards_point( other.x-10, other.y-10, 20 );  
            }      
           
        }
    
    global.SentryBatObject_x = x;
    global.SentryBatObject_y = y;
               
           
            //////////DOOOM DIFFICULTY///////////
    
    
    with(SentryBatObject)
    {
       
        doom_timer--;
       
        if (doom_timer <= 0 && global.doom_difficulty)
        {
            hp -= 20; //slowly drains health  
            doom_timer = room_speed;
        }
       
       
    }
    
    And the code for the step event for the simple brain

    Code:
    
    //SimpleBrainSentryBatCollision(x,y);
    
    if attackTarget != noone {
       if distance_to_object(attackTarget) > attackRange
          move_towards_point(attackTarget.x,attackTarget.y, flyspeed);
       else
       {
          speed=0;
          //do your attacking stuff for the bat and deal damage to attackTarget
       }
    }
    
    BrainBatCollision();
    
    
    //If you collide with the castle vanish
    if (path_position == 1)
    {
        //reached the castle)
        instance_destroy();
    }
    
    
    //collide with castle
    //castle_collision_timer--;
    
    //if (castle_collision_timer <= 0)
    //{
    if (collision_rectangle( 153,  800, 700, 1300, BigBrainObject, false, false ))
    {
       
            show_debug_message("Collide with Castle");
            //sprite_index = BigBrainAttacking;
            //attack the castle
            hp_minus = irandom_range(200, 500);
            global.castle_hp -= hp_minus;
    
            floater = instance_create_depth(x+10, y-10, -1700, DamageIndicatorObject);
            floater.text = string(hp_minus);
            castle_collision_timer = room_speed*5;
            instance_destroy();
    }
    //}
    
    
    
    
    //hit the castle
    if (x < 200)
    {
        instance_destroy();
    }
    
    
    //was hit by a snowball
    if (frozen)
    {
        path_speed =0;
        speed = 0;
        sprite_index = SnowBatStill;
        alarm[9] = room_speed;
    }
    
    //petrified
    if (global.petrification)
    {
        show_debug_message("Petrified");
        path_speed = 0;
        speed = 0
        sprite_index = PetrifiedBrain;
    }
    
    if (global.freeze_brains)
    {
        path_speed = 0;
        speed = 0;
        //sprite_index = BigBrainStill;
        alarm[9] = room_speed;
    }
    
    //hit by lightning
    was_hit_by_lit = false;
    
    
    
    
    //show_debug_message("lit_damage_timera: " + string(lit_damage_timera));
    //show_debug_message("lit_damage_timerb: " + string(lit_damage_timerb));
    //show_debug_message("lit_damage_timerc: " + string(lit_damage_timerc));
    
    if (global.active == true && collision_line(global.litorigin_x, global.litorigin_y, global.lightning_1_x, global.lightning_1_y, SimpleBrain, false, false))
    {
        lit_damage_timera--;
        show_debug_message("lit_damage_timera: " + string(lit_damage_timera));
        if (lit_damage_timera <= 0)
        {
           
            show_debug_message("Lit Timer A fire: ");
            hp_minus = irandom_range(100,400);
            damage = hp_minus;
            hp = hp - hp_minus;
            floater = instance_create_depth(x, y, -17000, DamageIndicatorObject)  
            floater.text = string(damage)
       
            under_attack = true;
            took_a_hit = true;
            was_hit_by_lit = true;
            lit_damage_timera = room_speed*4;
           
        }
    }
    
    
    if (global.active == true && collision_line(global.lightning_1_x, global.lightning_1_y, global.lightning_2_x, global.lightning_2_y, SimpleBrain, false, false))
    {
        lit_damage_timerb--;
    
        if (lit_damage_timerb <= 0)
        {
            show_debug_message("Lit Timer B fire: ");
            hp_minus = irandom_range(100,400);
            damage = hp_minus;
            hp = hp - hp_minus;
            floater = instance_create_depth(x, y, -17000, DamageIndicatorObject)  
            floater.text = string(damage)
       
            under_attack = true;
            took_a_hit = true;
            was_hit_by_lit = true;
            lit_damage_timerb = room_speed*4;
        }
    }
    
    
    if (global.active == true && collision_line(global.lightning_2_x, global.lightning_2_y, global.lightning_3_x, global.lightning_3_y, SimpleBrain, false, false))
    {
        lit_damage_timerc--;
        if (lit_damage_timerc <=0)
        {
           
            show_debug_message("Lit Timer C fire: ");
            hp_minus = irandom_range(100,400);
            damage = hp_minus;
            hp = hp - hp_minus;
            floater = instance_create_depth(x, y, -17000, DamageIndicatorObject)  
            floater.text = string(damage)
       
            under_attack = true;
            was_hit_by_lit = true;
            lit_damage_timerc = room_speed*4;
        }
    }
    
    if (was_hit_by_lit == true && global.active == false)
    {
        under_attack = false;
    }
    if (position_meeting(x, y, SimpleBrain))
    {
        SimpleBrain.y = SimpleBrain.y - 350;
    }
    
    
    
    
    
    
    /////////////////////////////////
    //Poison ZTimer
    //
    
    
    if (poisoned)
    {
       
        timer--;
        if (timer <= 0)
        {
            damage = irandom_range(0,20);
            hp_minus = damage;
            timer = 0;
            floater = instance_create_depth(x+10, y-10, -17000, DamageIndicatorObject);
            floater.text = string(hp_minus);
           
            if (hp <= 0)
            {
                show_debug_message("Dead Brain Ghost and Fading Gem");
                instance_create_depth(x, y, -1100,DeadBrainObject);      
                instance_create_depth(x-150, y-20, -1100, FadingGemObject);
                global.achievement_gold_counter++;
               
                global.achievement_tome_experience += 20;
                instance_destroy();
            }
            timer = room_speed;
        }
        under_attack = true;
        took_a_hit = true;
    }
       
    //////////END OF PATH/////////////////////
    
    
    
    
    
    
    
    if (global.freeze_brains)
    {
        path_speed = 0;
    }
    //else
    //{
    //    path_speed = 5;
    
       
    
    
    
    //////////////Attack on Castle Wall/////////////////////////
    
    if (point_in_rectangle(x-100, y, 156, 798, 714, 1277))
    {
        show_debug_message("Wall Collision");
    
        castle_wall_timer--;
       
        if (castle_wall_timer <= 0)
        {
            hp_minus = irandom_range(4, 50);
            global.castle_hp = global.castle_hp - hp_minus;
            path_end();
            sprite_index = SimpleBrainAttack;
    
            castle_wall_timer--;
    
            number_of_attacks++;
    
            if (number_of_attacks > 5)
            {
                instance_destroy();
            }
       
       
            castle_wall_timer = room_speed;
           
           
            floater = instance_create_depth(x+10, y-10, -17000, DamageIndicatorObject)    ;
            floater.text = string(hp_minus);  
            show_debug_message("Iterating through step wall timer");
        }
    
    
    
    }
    //////////////ATTACK ON INNERTUBE//////////////////////////
    
    if (point_in_rectangle(x, y, 46, 552, 346, 847))
    {
        show_debug_message("Wall Collision");
    
        castle_wall_timer--;
       
        if (castle_wall_timer <= 0)
        {
            hp_minus = irandom_range(50, 150);
            global.castle_hp = global.castle_hp - hp_minus;
            path_end();
            sprite_index = SimpleBrainAttack;
    
            castle_wall_timer--;
    
            number_of_attacks++;
    
           
           
            castle_wall_timer = room_speed;
           
           
            floater = instance_create_depth(x+10, y-10, -17000, DamageIndicatorObject)    ;
            floater.text = string(hp_minus);  
            show_debug_message("Iterating through step wall timer");
           
            if (number_of_attacks > 5)
            {
                number_of_attacks = 0;
                instance_destroy();
            }
       
        }
    
    
    
    }
    
    ///////////////////////////////////////////
    
    mind_timer--;
    
    if (global.mindbreak && mind_timer <= 0)
    {
        mind_timer = room_speed*3;
        path_number = irandom_range(0, 4);
        path_end();
        if (path_number == 0)
        {
            x++;
        }
        if (path_number == 1)
        {
            x--;
        }
        if (path_number == 2)
        {
            y++;
        }
        if (path_number == 3)
        {
            y--;
        }
       
       
    }
    
     
  22. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    Okay if you are not using parenting, then specifically which objects are you testing this with? Is the player specifically creating an instance of SentryBatObject and not any other kind of bat, and is the enemy specifically creating an instance of BigBrainObject and not any other kind of brain?

    Your project is going to have multiple types of bats and possibly multiple types of brains. In order to do that, you need to use parenting, or else you're using some other method to dictate how they are going to attack with different methods.

    The issue right now is that neither of the two variables are getting set because the game is not registering that you are clicking on either BigBrainObject or a child of BigBrainObject, nor on SentryBatObject or a child of SentryBatObject. the first time I have to make sure you're you are even using the right objects in your testing.
     
  23. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    Yes l guess I should use parenting. Right now the player specifically creates an instance of SentryBatObject and no other kind of bat.The enemy creates an instance of BigBrainObject and not any other kind of brain. So the code being tested is just for SentryBatObject and BigBrainObject. And so, yeah, the two variables aren't getting set, I get that much.
     
  24. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    Hmmm...

    First issue to correct that I missed:
    Code:
    
       with colliderbat
        attackTarget = other.colliderbrain;
    
       with colliderbrain
         if attackTarget == noone
            attackTarget = other.colliderbat;
         else
         if distance_to_object(attackTarget) > attackRange
            attackTarget = other.colliderbat;
    
    }
    I left out the other. prefixes in those lines. That will throw an error once we get past the current issue. lol

    Also, you NEED to check if n!=noone, or else the "object_index" checks will crash.
    Code:
      var n = instance_position(mouse_x,mouse_y, all);
      if n == noone return 0;
    
    Now, aside from those two errors, both of which were my bad, the code should work. At least, the code should be registering if a brain is clicked on and if a bat is clicked on. I just tested the main block of code in my own simple project, drawing text on-screen if and only if both colliderbrain and colliderbat got set. So then that leads to me consider a few possibilities.

    1) The code is in an event that cannot register the mouse, but when that would be, I'm not sure.

    2) Your bat and brain have a mask_index that is too small.

    3) Your bat and brain have neither a mask_index nor a sprite_index assigned.

    4) Your bat and brain's sprites have inappropriately sized bounding boxes.

    5) You are using this code in the Draw GUI event for some reason.

    Like I said, it worked for me just now. It required I click on a brain first, then a bat; if I clicked on a bat first, then the brain would cancel the bat and the text wouldn't show; if I clicked on emptiness, the text wouldn't show. So those are the five possibilities I could come up with as to why it's working for me but not you.
     
    IndianaBones likes this.
  25. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    744
    Man, hats off to @TheouAegis, its amazing how many posts you make helping people and they're always so in depth, I wish I had the time to do that, but I'd need to slow down time to at least 10%
     
  26. TheSly

    TheSly Member

    Joined:
    Jan 16, 2017
    Posts:
    801
    Absolutely! This site should have badges or something that recognises peoples tireless work. The amount of help he gives Ted alone would be worth about 10 of them. Total respect @TheouAegis for your effort.
     
    Taddio and rIKmAN like this.
  27. Taddio

    Taddio Member

    Joined:
    Nov 16, 2018
    Posts:
    421
    Word.
     
  28. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    I agree. @TheouAegis should deserve a medal. Or a donation for all his work with me. I'm still a beginner with GMS2 compared to @TheouAegis . Anyway, accolades aside, the
    pairing still isn't working. Out of the debug messages, only "Click off of sentry bat and brain" and "Mouse Check Button collision pressed" shows up

    Code:
    if mouse_check_button_pressed(mb_left) {
        show_debug_message("Mouse Check Button collision pressed");
      var n = instance_position(mouse_x,mouse_y, all);
      if n == noone return 0;
       if n.object_index == BigBrainObject || object_get_parent(n.object_index)==BigBrainObject
       {
           show_debug_message("Big Brain Object is selected");
         colliderbrain = n;
         colliderbat = noone;    //This may not work for you, but it would force the player to pick a new bat after clicking on a brain
       }
       else
       if n.object_index == SentryBatObject || object_get_parent(n.object_index)==SentryBatObject {
         colliderbat = n;
         show_debug_message("Sentry Bat Object is selected");
       }
       else {
           show_debug_message("Click off of sentry bat and brain");
          colliderbrain=noone;
          colliderbat=noone;
       }
      
       with colliderbat
         attackTarget = other.colliderbrain; 
    
        with colliderbrain
          if attackTarget == noone
             attackTarget = other.colliderbat;
          else
          if distance_to_object(attackTarget) > attackRange
             attackTarget = other.colliderbat;
    
    }
    
    I"m thinking it is
    Code:
    var n = instance_position(mouse_x,mouse_y, all);
    .Should we be using "all"?

    Also, is this kosher? (It's right under the the pairing code)

    Code:
    with colliderbrain
    {   
        show_debug_message("With colliderbrain");
            with attackTarget
            {
                
                //damage to batq
                if (!global.group_invincibility)
                {
                    hp = hp - 1;
                    damage = 1;
                    damage_dealt_to_bat = damage;
                }
        
            }
        
            ///colliderbrain is Brain
            show_debug_message("With colliderbrain");
            
                    
            sprite_index = SimpleBrainAttack;
            
            
            //under_attack = true;
            //took_a_hit = true;
                        //sprite_index = SentryBatAttack
                        //image_speed = 1;
            audio_play_sound(BatThumpSound,20,false);
                    
            show_debug_message("Showing Damage Indicator");
                    
                        
                    
            //killl the brain   
            if (hp <= 0)
            {
                show_debug_message("Kill the brain");
                        
                global.achievement_gold_counter++;
                global.achievement_tome_experience += 20;
                show_debug_message("Dead Brain Ghost and Fading Gem");
                audio_play_sound(DieingBrainSound, 20, false);
                instance_create_depth(x, y, -1100,DeadBrainObject);       
                instance_create_depth(x-150, y-20, -1100, FadingGemObject);
                instance_destroy();
            }
        
    }
    
    I'm just trying to explore all the possibilities.
     
  29. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    Right now I'm just trying to figure out why you can't click on anything. Right now you can't even get to the "kosher" code. We can worry about that when we get to it. And no it can't be that all because like I said, it works just fine for me. So verify the five points that I listed in the last post. Check your sprites, check your object properties, check what event the code is in.
     
  30. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    Ok. So.

    1) I don't know how to check that.
    2) The masks are rectangles that encompass the entire sprite
    3) Don't know how to check this.
    4) See 2.
    5) Not in a Draw GUI. I never use Draw GUI.

    Boy I feel dumb now..


    So, BrainBatCollision() in SimpleBrain's step event is where I put the following:

    Code:
    if mouse_check_button_pressed(mb_left) {
        show_debug_message("Mouse Check Button collision pressed");
      var n = instance_position(mouse_x,mouse_y, all);
      if n == noone return 0;
       if n.object_index == BigBrainObject || object_get_parent(n.object_index)==BigBrainObject
       {
           show_debug_message("Big Brain Object is selected");
         colliderbrain = n;
         colliderbat = noone;    //This may not work for you, but it would force the player to pick a new bat after clicking on a brain
       }
       else
       if n.object_index == SentryBatObject || object_get_parent(n.object_index)==SentryBatObject {
         colliderbat = n;
         show_debug_message("Sentry Bat Object is selected");
       }
       else {
           show_debug_message("Click off of sentry bat and brain");
          colliderbrain=noone;
          colliderbat=noone;
       }
      
       with colliderbat
         attackTarget = other.colliderbrain; 
    
        with colliderbrain
          if attackTarget == noone
             attackTarget = other.colliderbat;
          else
          if distance_to_object(attackTarget) > attackRange
             attackTarget = other.colliderbat;
    
    }
    
    with colliderbrain
    {   
        show_debug_message("With colliderbrain");
            with attackTarget
            {
                
                //damage to batq
                if (!global.group_invincibility)
                {
                    hp = hp - 1;
                    damage = 1;
                    damage_dealt_to_bat = damage;
                }
        
            }
        
            ///colliderbrain is Brain
            show_debug_message("With colliderbrain");
            
                    
            sprite_index = SimpleBrainAttack;
            
            
            //under_attack = true;
            //took_a_hit = true;
                        //sprite_index = SentryBatAttack
                        //image_speed = 1;
            audio_play_sound(BatThumpSound,20,false);
                    
            show_debug_message("Showing Damage Indicator");
                    
                        
                    
            //killl the brain   
            if (hp <= 0)
            {
                show_debug_message("Kill the brain");
                        
                global.achievement_gold_counter++;
                global.achievement_tome_experience += 20;
                show_debug_message("Dead Brain Ghost and Fading Gem");
                audio_play_sound(DieingBrainSound, 20, false);
                instance_create_depth(x, y, -1100,DeadBrainObject);       
                instance_create_depth(x-150, y-20, -1100, FadingGemObject);
                instance_destroy();
            }
        
    }
    
    with colliderbat
    {
        sprite_index = SentryBatAttack;
        
        with attackTarget
        {
            hp_minus = irandom_range(10, 50);
            hp = hp - hp_minus;
                
        
            floater = instance_create_depth(x+10, y-10, -17000, DamageIndicatorObject);
            floater.text = string(hp_minus);
        }
            
            
        if (hp <= 0)
        {
            audio_play_sound(BatDeathSound, 20, false);
            instance_create_depth(x, y, -1100,DeadBatObject);
            global.num_sentry_killed++;
            instance_destroy();
                            
                
        }
        
    }
    Also in Simple Brain's step I put:
    Code:
    if attackTarget != noone {
       if distance_to_object(attackTarget) > attackRange
          move_towards_point(attackTarget.x,attackTarget.y, flyspeed);
       else
       {
          speed=0;
          //do your attacking stuff for the bat and deal damage to attackTarget
       }
    }
    
    Also in Sentry Bat's step I put:

    Code:
    if attackTarget != noone {
       if distance_to_object(attackTarget) > attackRange
          move_towards_point(attackTarget.x,attackTarget.y, flyspeed);
       else
       {
          speed=0;
          //do your attacking stuff for the bat and deal damage to attackTarget
       }
    }
    
     
  31. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    BatBrainCollision should be called inside of a separate, controller object, neither in the bat nor the brain.

    I'm not sure why that would affect anyting, but that is the basis of the logic of the code.
     
  32. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    I have separate controllers for the brains and for the bats. I don't know....should I create a separate controller just for the BatBrainCollisions..? IDK
     
  33. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    Yes. At least it won't hurt for now. If there is still an issue even with that, then at least we ruled it out. but the reason you don't want that code inside of either brain or the bat is because if you have more than one brain or more than one bat active than that code is going to get run multiple times needlessly.

    As for point 3, you'd probably k ow if sprite_index is not set, as you would have to use a Draw event just to even see the bat or brain.
     
  34. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    Alright @TheouAegis . I created an object for a controller called MasterController. I put a call to the function BrainBatCollision in the step event of MasterControlller. I added MasterController to the Level One Room. This is what happened w hen I ran it:

    upload_2019-4-11_0-52-44.png
     
  35. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    Cuz you left this line out from my code:


    if !colliderbrain || !colliderbat return 0; //If either target hasn't been chosen, end the script for now
     
  36. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    Hi @TheouAegis . So I fixed that mistake of mine. I have created a Master Controller that calls your script (the pairing script) in the step event. I put the Master Controller object in the game room.
    So I got a an error saying that:

    It said that for both. So I added colliderbrain = noone and colliderbat = noone to the top of the script.
    My sentrybat isn't attacking and when Itry to retreat it lets me retreat somewhat but then gets stuck. I can
    only retreat backwards, not upwards or on any angles.

    So does this attack code in the script look right?

    Code:
    
    //test
    
    //colliderbrain = noone;
    //colliderbat = noone;
    //test
    if mouse_check_button_pressed(mb_left) {
        show_debug_message("Mouse Check Button collision pressed");
      var n = instance_position(mouse_x,mouse_y, all);
      if n == noone return 0;
       if n.object_index == BigBrainObject || object_get_parent(n.object_index)==BigBrainObject
       {
           show_debug_message("Big Brain Object is selected");
         colliderbrain = n;
         colliderbat = noone;    //This may not work for you, but it would force the player to pick a new bat after clicking on a brain
       }
       else
       if n.object_index == SentryBatObject || object_get_parent(n.object_index)==SentryBatObject {
         colliderbat = n;
         show_debug_message("Sentry Bat Object is selected");
       }
       else {
           show_debug_message("Click off of sentry bat and brain");
          colliderbrain=noone;
          colliderbat=noone;
       }
     
       //Now that we may have established a brain-bat pairing, we can move on
        if !colliderbrain || !colliderbat return 0;    //If either target hasn't been chosen, end the script for now
     
       with colliderbat
         attackTarget = other.colliderbrain;
    
        with colliderbrain
          if attackTarget == noone
             attackTarget = other.colliderbat;
          else
          if distance_to_object(attackTarget) > attackRange
             attackTarget = other.colliderbat;
    
    }
    
    with colliderbrain
    {  
        show_debug_message("With colliderbrain");
            with attackTarget
            {
               
                //damage to batq
                if (!global.group_invincibility)
                {
                    hp = hp - 1;
                    damage = 1;
                    damage_dealt_to_bat = damage;
                }
       
            }
       
            ///colliderbrain is Brain
            show_debug_message("With colliderbrain");
           
                   
            sprite_index = SimpleBrainAttack;
           
           
            //under_attack = true;
            //took_a_hit = true;
                        //sprite_index = SentryBatAttack
                        //image_speed = 1;
            audio_play_sound(BatThumpSound,20,false);
                   
            show_debug_message("Showing Damage Indicator");
                   
                       
                   
            //killl the brain  
            if (hp <= 0)
            {
                show_debug_message("Kill the brain");
                       
                global.achievement_gold_counter++;
                global.achievement_tome_experience += 20;
                show_debug_message("Dead Brain Ghost and Fading Gem");
                audio_play_sound(DieingBrainSound, 20, false);
                instance_create_depth(x, y, -1100,DeadBrainObject);      
                instance_create_depth(x-150, y-20, -1100, FadingGemObject);
                instance_destroy();
            }
       
    }
    
    with colliderbat
    {
        sprite_index = SentryBatAttack;
       
        with attackTarget
        {
            hp_minus = irandom_range(10, 50);
            hp = hp - hp_minus;
               
       
            floater = instance_create_depth(x+10, y-10, -17000, DamageIndicatorObject);
            floater.text = string(hp_minus);
        }
           
           
        if (hp <= 0)
        {
            audio_play_sound(BatDeathSound, 20, false);
            instance_create_depth(x, y, -1100,DeadBatObject);
            global.num_sentry_killed++;
            instance_destroy();
                           
               
        }
       
    }
    And can you verify the step events In the Sentry bat?

    Code:
    if (hp <= 0)
    {
        instance_destroy();
    }
    
    
    if attackTarget != noone {
       if distance_to_object(attackTarget) > attackRange
          move_towards_point(attackTarget.x,attackTarget.y, flyspeed);
       else
       {
          speed=0;
          //do your attacking stuff for the bat and deal damage to attackTarget
       }
    }
    
            if (flight == true)
            {  
               
                           
                   
               
                if (!global.acceleration)
                {
                    if (point_distance(x, y, target_placement_x-100, target_placement_y-100) > 15)
                    {
                        play_timer--;
                        if (played == false)
                        {
                            audio_play_sound(BatWingsMovementSound, 20, false);
                            played = true;
                        }
                        if (play_timer <= 0)
                        {
                            played = false;
                            play_timer = room_speed*2;
                        }
                   
                        sprite_index = SentryBatWalk;
                        move_towards_point( target_placement_x-100, target_placement_y-100, 10 );  
                        global.dropped_bat = false;
                       
                    }
                    else
                    {
                        speed = 0;
                        flight = false;
                        sprite_index = SentryBatIdle;
                    }
                }
               
                else
                {
                    if (point_distance(x, y, target_placement_x-100, target_placement_y-100) > 40)
                    {
                       
                        play_timer--;
                        if (played == false)
                        {
                            audio_play_sound(BatWingsMovementSound, 20, false);
                            played = true;
                        }
                        if (play_timer <= 0)
                        {
                            played = false;
                            play_timer = room_speed*2;
                        }
                   
                       
                                       
                        sprite_index = SentryBatWalk;
                        move_towards_point( target_placement_x-100, target_placement_y-100, 30 );  
                        global.dropped_bat = false;
                    }
                    else
                    {
                        speed = 0;
                        flight = false;
                        sprite_index = SentryBatIdle;
                    }
               
               
                }
            }
           
       
    
        //if invincible
        if (global.group_invincibility == true)
        {
            //if the cross doesn't already exist
            if (!object_exists(AlchemistInvincibleObject))
            {
                //create a cross
                inst = instance_create_depth(x+110, y+110, -1100, AlchemistInvincibleObject);
            }
            //move sentry bats along wi                  th the bat
            //cross
            with (AlchemistInvincibleObject)
            {
                x = other.x;
                y = other.y;
                move_towards_point( other.x-10, other.y-10, 10 );  
            }      
           
        }
       
    ///////////////////////ACCELERAtion///////////////
    
    //if invincible
        if (global.acceleration)
        {
            //if the cross doesn't already exist
            if (!object_exists(AccelerationBuff))
            {
                //create a lightning bolt
                inst = instance_create_depth(x+110, y+110, -1100,AccelerationBuff);
            }
            //move sentry bats along wi                  th the bat
            //cross
            with (AccelerationBuff)
            {
                //x = other.x;
                //y = other.y;
                if distance_to_point(other.x-10,other.y-10) < 20
                {
                    x = other.x-10;
                    y = other.y-10;
                    speed = 0;
                }
       
               
                move_towards_point( other.x-10, other.y-10, 20 );  
            }      
           
        }
    
    global.SentryBatObject_x = x;
    global.SentryBatObject_y = y;
               
            
       
    }
       
    
    And simple brain step event
    Code:
    //SimpleBrainSentryBatCollision(x,y);
    
    if attackTarget != noone {
       if distance_to_object(attackTarget) > attackRange
          move_towards_point(attackTarget.x,attackTarget.y, flyspeed);
       else
       {
          speed=0;
          //do your attacking stuff for the bat and deal damage to attackTarget
       }
    }
    
     
  37. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    You only set colliderbrain and colliderbat to noone in the Create Event and when the player clicks on something other than a brain or bat. You do NOT want to reset them every time the script is called, since the player needs time to click on one instance and then another.


    You MUST put the conditional I mentioned back in here. You took it out when you tried to optimize my code, but it was one part of my code that was critical.

    Code:
    if mouse_check_button_pressed(mb_left) {
    ...
    ...
    } 
    
    if !colliderbrain || !colliderbat return 0;
    
    with colliderbrain...
    
     
  38. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    Ok. The conditional is put back in. The colliderbat and colliderbrain are only set to noone when player clicks on something other than a brain or bat or in the create event of the controller. I'm clicking on the bat then the brain then on the bat then on the brain and so on. I'm not sure if the pairing is working or if its the attack code. suggestions?
     
  39. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    The required order is brain then bat. If you go bat then brain, you would need to click on the bat again. Of course you can change this around a little bit by changing the structure of that very first block.

    The way I tested my code was I had a GUI draw event in the controller object. I had it draw the values of colliderbrain and colliderbat at all times. If I clicked on a brain, I would see that brain's ID. If I then clicked on a bat, I would also see that bat's ID. Since in my demo I didn't do anything at that point, the two numbers stayed on my screen. Then I clicked onthe room somewhere other than either a brain or a bat, and both numbers went to -4. I then clicked on a bat, the bat ID showed up. then I clicked on the brain and the Brain ID showed up but the bat ID was reset to -4. And I clicked on the bat again and the bat ID showed back up and again both the brain ID and the bat ID were drawn in my GUI. after that I knew that my code was properly setting the variables colliderbrain and colliderbat. It is at that point when colliderbrain and colliderbat are both set to IDs that they are technically paired.

    So do that, use the GUI event in the controller object to verify in real time on screen that the brain and/or bat are getting selected and he selected properly. I will try to look through the rest of your code in the meantime. I've got the flu or something right now - although the doctor says it's not the flu but it doesn't feel like a freaking cold either - so I'm not spending too much time on GM stuff this week.

    Side note:
    that conditional that I had you put back in which I said was critical is the conditional which checks if they are paired. The reason it was a critical conditional is because it follows the logic pattern

    If A then B;
    If A then not C;
    If C then D;
    If B and D then E

    But you took out that conditional, which left you with

    If A then B;
    If A then not C;
    If C then D;
    B and D;
    Therefor E

    By removing that conditional, the code became presumptuous that both variables had been set, which is not how the code works.
     
  40. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609

    Ok. So where should I put the main script? The GUI event or the Step Event? And how do I access the colliderbrain and batbrain in the GUI? FOr example:

    Draw GUI:

    Code:
    BrainBatCollision();
    draw_text_transformed_color(400, 100, "colliderbat: " + string(colliderbat.object_index), 2, 2, 0, c_black, c_black, c_black, c_black, 1);
    draw_text_transformed_color(400, 100, "colliderbrain: " + string(colliderban.object_index), 2, 2, 0, c_black, c_black, c_black, c_black, 1);
     
  41. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    BrainBatCollision() goes in the Step Event.

    The GUI event needs to account for colliderbat/brain being noone sometimes.
    Code:
    if colliderbat==noone draw_text(400,100,"Colliderbat: Not Selected");
    else draw_text(400,100,"Colliderbat: Selected")
    if colliderbrain==noone
    draw_text(400,132,"Colliderbrain: Not Selected")
    else draw_text(400,132,"Colliderbrain: Selected");
     
  42. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    Hmm...……….everything seems like it should be right, but can't seem to select the bat or brain according to your GUI code.
     
  43. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    Is it showiing

    Colliderbat: Selected
    Colliderbrain: Selected

    or is it showing

    Colliderbat: Not Selected
    Collider Brain: Not Selected

    ? Do either of them ever come up as "Selected" or are they always "Not Selected"?


    Two issues I have with your code, now that I've looked over the rest of it again:
    1. You aren't setting colliderbrain and colliderbat back to noone after they have been paired. This is fine for debugging things, because you can't see them paired if you're clearing them immediately after pairing; but it's still a part of my original code.
    2. That block of code that you asked if it was "kosher" should NOT be part of BatBrainCollision(); it should go inside the bat and brain objects respectively. By including that "kosher?" block of code inside the script. you are forcing the game to essentially say, "So long as this bat and this brain are currently selected, then only this bat and this brain are able to do any combat and all other bats and brains must wait until I click them again." That...is a very unusual game mechanic. The typical mechanic is you tell the bat which brain will be its target and then you let the bat attack its target; you then tell the brain which bat is trying to attack it so it can counterattack the bat targeting it. Whether or not you allow multiple bats to attack a single brain is another issue, but the point is the bat and brain are allowed to carry on outside of the script. The sole purpose of the script itself is simply to generate attacker-defender pairs. (And typing this out, it seems more logical to force the player to click on the bat first and THEN click on a brain for the bat to attack, rather than the brain first.)
     
    Last edited: Apr 15, 2019
  44. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    It is showing:

    Colluderbat: Not Selected
    Collider brain: Not Selected.
    They are always selected.

    Parts I'm not quite getting:

    1. Why woujld the two be set back to noone after they have been paired. I thought the whole idea was to assign a bat and brain to colliderbrain and colliderbat so that the two can attack each other?
    2. So should that " kosher" code go in the step events of the bats and brains. If so, how do I get to the colliderbrain and colliderbat pairs from the "kosher" code. Is that the point of this?
    Shouldn't I pair a colliderbrain and colliderbat and then when the "kosher" code in the step event fires in the bat for instance, the brain code would cause damage to the colliderbat. Then when
    the bat code "kosher" in the step event would fire and the bat would cause damage to the colliderbrain.

    Am I in the in the right ballpark?

    -TW
     
  45. Edwin

    Edwin Member

    Joined:
    Jul 15, 2018
    Posts:
    337
    You post threads so often :)
     
  46. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    You don't use colliderbrain and colliderbat outside of the controller object. The two variables are strictly for the controller object to keep track of when a suitable pair has been clicked. Once a pair has been properly clicked (in the current situation, brain first then bat), the controller object (via this script) tells the bat whose ID is stored in its colliderbat which brain to attack via the bat's own attackTarget variable, then tells the brain which bat to attack via the brain's own attackTarget variable. And then the controller resets colliderbrain and colliderbat back to noone because it's done with the two varaibles until the next time a pairing needs to be made. The bat and the brain act on their own accordingly to each one's attackTarget.

    If you remove the "kosher?" code completely for not (or just comment it all out), then the pairing should work just fine, resulting in "Selected" being shown when you click on a bat or brain.

    As for what the "kosher?" code should do, it should check if the brain or bat is in attack range of attackTarget and if it is, perform its attack animation and deal damage to attackTarget. Every bat will have its own attackTarget. Every brain will have its own attackTarget. The "kosher" code should simply say, "move toward attackTarget until the distance to attackTarget is less than my attackRange and then attack, dealing damage to attackTarget." The brain doesn't control the bat. The bat doesn't control the brain. The controller object doesn't even control either of them, it just directs them to what the player wants them to do.
     
  47. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    Ok. Well that makes sense. Except I don't know how the GUI event can access colliderbrain and colliderbat's pairing. I removed the "kosher?"" code a while back. I think I understand everything but the pairing isn't happening. So there must be something wrong with how i'm doing the pairing.I have a controller object with the GUI code you told me to write and I call the pairing script in the step event. At this point I'm just trying to get them to pair so right now I don't have any other related code.

    @Edwin This is complicated stuff.
     
  48. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    The GUI event is inside the same object that's calling BatBrainCollision(), so colliderbat and colliderbrain are accessible in all the events of that controller object. The pairing itself doesn't exist, it's just an aspect of the bats and brains. I'll try to make the GUI a little clearer farther down this post.

    Code:
    if mouse_check_button_pressed(mb_left) {
       show_debug_message("Mouse Check Button collision pressed");
      var n = instance_position(mouse_x,mouse_y, all);
      if n == noone return 0;
       if n.object_index == BigBrainObject || object_get_parent(n.object_index)==BigBrainObject
       {
          show_debug_message("Big Brain Object is selected");
        colliderbrain = n;
        colliderbat = noone;    //This may not work for you, but it would force the player to pick a new bat after clicking on a brain
       }
       else
       if n.object_index == SentryBatObject || object_get_parent(n.object_index)==SentryBatObject {
        colliderbat = n;
        show_debug_message("Sentry Bat Object is selected");
       }
       else {
          show_debug_message("Click off of sentry bat and brain");
         colliderbrain=noone;
         colliderbat=noone;
       }
    
       //Now that we may have established a brain-bat pairing, we can move on
       if !colliderbrain || !colliderbat return 0;    //If either target hasn't been chosen, end the script for now
    
       with colliderbat
           attackTarget = other.colliderbrain;
    
       with colliderbrain
         if attackTarget == noone
            attackTarget = other.colliderbat;
         else
         if distance_to_object(attackTarget) > attackRange
            attackTarget = other.colliderbat;
    }
    So is this code the ONLY code inside BatBrainCollision() now?

    Once we get this better figured out, you need to change this line:
    Code:
    if n == noone return 0;
    to this instead:
    Code:
    if n == noone {
        colliderbrain = noone;
        colliderbat = noone;
    }
    else
    I had put in that "if n==noone return 0;" line to avoid a missing object error. What I didn't realize at the time that I wrote it was it limited the other part that resets colliderbrain and colliderbat to only work when clicking on non-bat and non-brain objects, but wasn't allowing them to get reset when clicking on no objects at all. So now it's just one long chain of if-else-if-else: If we didn't click on anything, reset the variables; else if we clicked on a bat, set colliderbat; else if we clicked on a brain, set colliderbrain; else [if we clicked on anything else] reset the variables.

    Now, right after this part of the code:
    Code:
    with colliderbrain
         if attackTarget == noone
            attackTarget = other.colliderbat;
         else
         if distance_to_object(attackTarget) > attackRange
            attackTarget = other.colliderbat;
    Add these two lines to reset colliderbat and colliderbrain (this is all still inside the main if mouse_check_button_pressed(mb_left) conditional block):
    Code:
    colliderbat = noone;
    colliderbrain = noone;
    
    This is what you need to make it so after the "pairing" (like I said, it's an aspect of two instances and doesn't actually exist) the selections are reset.
    So now the full code should look like
    Code:
    
    if mouse_check_button_pressed(mb_left) {
       show_debug_message("Mouse Check Button collision pressed");
      var n = instance_position(mouse_x,mouse_y, all);
      if n == noone
      {
          show_debug_message("Click on empty space")
          colliderbrain = noone;
          colliderbat = noone;
       }
       if n.object_index == BigBrainObject || object_get_parent(n.object_index)==BigBrainObject
       {
          show_debug_message("Big Brain Object is selected");
          colliderbrain = n;
          colliderbat = noone;    //This may not work for you, but it would force the player to pick a new bat after clicking on a brain
       }
       else
       if n.object_index == SentryBatObject || object_get_parent(n.object_index)==SentryBatObject
       {
          colliderbat = n;
          show_debug_message("Sentry Bat Object is selected");
       }
       else
       {
          show_debug_message("Click wrong object type");
         colliderbrain=noone;
         colliderbat=noone;
       }
    
       //Now that we may have established a brain-bat pairing, we can move on
       if !colliderbrain || !colliderbat return 0;    //If either target hasn't been chosen, end the script for now
    
       with colliderbat
           attackTarget = other.colliderbrain;
    
       with colliderbrain
         if attackTarget == noone
            attackTarget = other.colliderbat;
         else
         if distance_to_object(attackTarget) > attackRange
            attackTarget = other.colliderbat;
    
        colliderbat = noone;
        colliderbrain = noone;
    }

    Now to help you visualize the pairing, assuming there isn't some other underlying issue elsewhere. Go into the GUI event, delete that old code I had you use, and then add this code:
    Code:
    with SentryBatObject if attackTarget != noone {
        draw_text(400,100,string(id)+" PAIRED WITH "+string(attackTarget));
        break;
    }
    Now when you click on a brain and then click on a bat, text similar to 1000145 PAIRED WITH 1000148 should appear on the screen. Then you will know at least those two instances are paired up.

    If you run the game with these changes and you cannot get that message to pop up at all no matter what you do, then your problem is outside of this script itself, because this final script works insofar as it pairs up a brain and a bat.
     
  49. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    609
    Well the script isn't working. I don't get a "PAIRED WITH" at all. Does that mean that attackTarget == no one?
    Otherwise *something* should show up.
     
  50. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,436
    Post the full object info for that controller object.

    Also post the object properties (not the code) for your brain and bat.

    How fast are your bat and brain moving? Try making them not move at all so they are easier to click on.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice