Hi,

Anyone one know how I can stop Godot warning me about my integer division (it is intentional). I have tried clicking the [Ignore], which inserts a @warning_ignore line, but it still warns me

Obviously I am just ignoring it but the little warning marker is useful to me, but now I ignore it and miss actual problems.

Many thanks

  • cybereality The logic looks fine to me assuming it's part of the code that increments the score and prevScore holds the score before the increment. It checks if score went over a threshold for the next extra life. It's sill somewhat bug prone because it doesn't properly handle the edge case of large increments where you can get multiple extra lives at once.

    Imho it's always better to keep the score as a float value (and only display it as an integer) because you never know what type of scoring calculations you may need to implement down the line. For example, if something is initially worth 1 point and you later decide to add some mechanic that can give the player a temporary +75% score boost, that score is now 1.75 and integer score tracking wouldn't accumulate the score properly.

    So to make this bulletproof, I'd track the score in an explicitly declared float variable, display it as a rounded int and do the extra life check like this:

    var extra_lives = int(global.score/global.extraLifeEvery) - int(prevScore/global.extraLifeEvery)
    while extra_lives > 0:
    	# add extra life here
    	extra_lives -= 1

    Handles multiple extra lives properly and no integer division warnings.

You can disable the warning in Project Settings -> Debug -> GDScript -> Integer Division.
To avoid it just via code, you can cast both operands to float and then cast the result back to int: var c = int(float(a)/float(b))

The reason that the @warning_ignore isn't working is that you may need two of them, since there are two integer divisions:

@warning_ignore("integer_division")
@warning_ignore("integer_division")
... line of code with the two integer divisions ...

However, I prefer xyz's casting solution. It makes the code clearer.

But you may need to do this instead, depending on what result you want:
if int(a)/int(b) > int(c)/int(d):

Thanks for your responses.

It does look like this is a bug in the editor, and as you rightly stated @DaveTheCoder it is because the integer division occurs twice on the same line

So:
@warning_ignore("integer_division")
result = n1 / n2

Happily ignores the warning about n1 and n2 being integers.
I did try multiple ignore statements, and @warning_ignore("integer_division", "integer_division") but they still persisted. I also do not want to disable the warning project wide as this is what I class as a gdscript quirk (it doesn't make obvious sense) so want to be warned if I do it elsewhere incase it is not expected.

So I have opted for the casting of them to float (thanks @xyz) whilst I disagree it is clearer and my OCD says it is sub optimal, for the sake of this problem it works 🙂

Cheers

    Why are you casting them as ints, tho? The comparison will be the same with floats without the cast.

      cybereality Yup your right there, so it becomes:

      if float(global.score) / float(global.extraLifeEvery) > float(prevScore) / float(global.extraLifeEvery):

      Actually two of those float casts can also go but it makes things probably less 'cleaner'?

      if float(global.score) / global.extraLifeEvery > float(prevScore) / global.extraLifeEvery:

      • xyz replied to this.

        What types are those variables? I don't think any cast is necessary.

        In fact, you are dividing by the same value. It works the same if you do this:

        if global.score > prevScore:

        But actually the logic is incorrect, you probably want to do this:

        if global.score - prevScore > global.extraLifeEvery:

        flossythesheep Wouldn't it be simpler to just explicitly declare your score tracking variable(s) as float? Then you needn't worry about any of this.

        They shouldn't be float, it's just logic that makes no sense.

        • xyz replied to this.

          cybereality The logic looks fine to me assuming it's part of the code that increments the score and prevScore holds the score before the increment. It checks if score went over a threshold for the next extra life. It's sill somewhat bug prone because it doesn't properly handle the edge case of large increments where you can get multiple extra lives at once.

          Imho it's always better to keep the score as a float value (and only display it as an integer) because you never know what type of scoring calculations you may need to implement down the line. For example, if something is initially worth 1 point and you later decide to add some mechanic that can give the player a temporary +75% score boost, that score is now 1.75 and integer score tracking wouldn't accumulate the score properly.

          So to make this bulletproof, I'd track the score in an explicitly declared float variable, display it as a rounded int and do the extra life check like this:

          var extra_lives = int(global.score/global.extraLifeEvery) - int(prevScore/global.extraLifeEvery)
          while extra_lives > 0:
          	# add extra life here
          	extra_lives -= 1

          Handles multiple extra lives properly and no integer division warnings.

          Ok I withdraw my previous post, the int() casting is needed, I just got lost in a type conversion sprial of doom 🙂

          So the comparison is a threshold detection. So every X points it is awarding an extra life. It is called every time the player scores anything.

          So given the following and say the player scores 10 points:
          global.extraLifeEvery = 1000
          prevScore = 999 # The score before the points were added
          global.score = 1009 # The current score (prevScore plus the 10 points scored)

          current factor = 1009 / 1000 = 1.009 int(1)
          previous factor = 999 / 1000 = 0.999 int(0)

          I cant use just the float value because current factor will always be greater than previous factor. So casting it to an integer gives it in steps of global.extraLifeEvery.

          int(currentFactor) > int(previousFactor)
          AddExtraLife

          As Godot loses any fractional part of an integer division naturally I could just do no casting, however that presents exactly the problem of the OP. Godot will flag two warning messages.
          To avoid the warnings (because the ignore doesn't work) casting to a float is required, but then I need to cast back to int to get the stepping type value.

          if int(float(global.score) / global.extraLifeEvery)) > int(float(prevScore) / global.extraLifeEvery)):

          Hope this all makes sense.

          • xyz replied to this.

            This still makes no sense. Let's say you have an equation:

            A / X < B / X

            That's the same as:

            A < B

            The X on both sides cancel out.

              cybereality This still makes no sense. Let's say you have an equation:
              A / X < B / X
              That's the same as:
              A < B
              The X on both sides cancel out.

              Strictly mathematically speaking it's not an equation but an inequality. You can't cancel inequalities the same way as equations because if X is a negative number then dividing both sides by X switches the inequality around.

              In this specific case it's not the same when you round/cast both sides to integers (or do integer divisions). This is exactly the point here, as @flossythesheep elaborated in their last post, to determine if X goes into A more times than it goes into B.

              cybereality Your right if you have that equation and they are all floats, but it is ignoring what godot does with an integer division (loses its fractional component) which creates the equivalent of:

              int(A/X) < int(B/X)
              Which is not the same as
              A < B

              I think I confused the situation in my type casting rabbit hole when I mistakenly thought I could get rid of the int cast in that line.

              @xyz That is a good call there, although I hadn't planned on the niche case of crossing multiple thresholds, ya never know

              Thanks all for your help here, much appreciated. At least I can move on without those warnings and a better system, happy times.

              Do whatever you want if you don't want help. Still makes no sense.

              Okay, so I'm kind of upset that neither of you are actually reading any of my posts, when I'm trying to help. But I'll try to explain this for a 5 year old and then I'm done here.

              My understanding is that global.extraLifeEvery is a value that indicated how many points you need to get an extra life (like 100 coins in Mario). So let us say that value is 100.

              The global.score is your current score, and prevScore is the last score since you last got an extra life. Let's say that the current score is 350 and the previous score is 200 (since we are giving extra lives every 100 points).

              Your logic is this:

              if int(float(global.score) / global.extraLifeEvery)) > int(float(prevScore) / global.extraLifeEvery)):

              If we plug in the numbers, it makes this:

              if int(float(350) / 100)) > int(float(200) / 100)):

              Now if we do the cast and division (since a float and an int will promote to float:

              if int(350.0 / 100.0)) > int(200.0 / 100.0)):
              if int(3.5) > int(2.0)):

              Cast to int:

              if 3 > 2:

              So, it's true, which is technically correct. But it's confusing and obtuse logic.

              What you are describing is a score that is above a threshold, which is the amount you need for an extra life above the previous score. Which is easily described with this inequality:

              if global.score - prevScore > global.extraLifeEvery:
              if 350 - 200 > 100:
              if 150 > 100:

              Which is true and more accurate describes what you are meaning to check for, with no unneeded division or multiple casts. Hope that makes sense.