I have a feeling I'm overlooking something stupid here...
By default all of my enemy objects start without a target assigned to them. As in - "target = noone;"
However, despite target being undefined I'm still erroring out from things being erroneously run inside of a code block that should only run if the enemy object has a target.
I have the if statement...
if(target != noone)
and have even tried...
if(!is_undefined(target))
... and in both cases there are lines being run that will cause my program to crash. Such as checking the distance between the target, turning to face the target, etc. All of these lines should never be getting run since they are within a block of code that should only run if the if statement check shows there is actually a target.
The entire code block is...
// If there is a target...
if(!is_undefined(target))
//if(target != noone)
{
// TARGET CONDITION CHECKS
// Check the distance to target.
var tdist = distance_to_object(target)
// Check if it is within firing range...
if(tdist < range_actual) then target_in_range = true else target_in_range = false;
// Check the difference in angles between the turret and its target
var pd = point_direction(x, y, target.x, target.y);
var dd = angle_difference(direction, pd);
// Check if the (absolute value of the) angle difference is within the weapons tolerance enough for the target to be considered within the firing arc of the weapon.
if(abs(dd) < angle_tolerance) then target_in_firing_arc = true else target_in_firing_arc = false;
//Rotate towards target using the above angle difference (dd)
direction -= min(abs(dd), rotation_speed) * sign(dd);
// If the target is within firing range...
// If they are also within the firing arc, and not reloading, then tell the weapon to start firing.
if(target_in_range = true && target_in_firing_arc && status != "reloading")
{
{
status = "firing"
}
}
// If the target isn't in range then start hoofing it them.
if(!target_in_range)
{
speed += acceleration;
if(speed > max_speed) then speed = max_speed;
xPos = x + lengthdir_x(speed, direction);
yPos = y + lengthdir_x(speed, direction);
if(place_meeting(xPos, yPos, obj_Col_Parent) && instance_place(xPos, yPos, obj_Col_Parent) != id) then speed = 0;
if(place_meeting(xPos, yPos, obj_player)) then speed = 0;
}
else // If they are in range then start to come to a stop.
{
if(point_distance(x, y, target.x, target.y) < range_actual / 2)
{
speed -= braking;
if(speed < 0) then speed = 0;
}
}
}
When using "if(target != noone)" to start my if statement block it will error out on line 87 which is "var tdist = distance_to_object(target)" and if I instead start the if statement with "if(!is_undefined(target))" then it will get just a bit further and error out on line 93 which is "var pd = point_direction(x, y, target.x, target.y);"
Anyone out there see what exactly I'm doing wrong?
I can't figure out why any lines of code in that if statement would ever be getting run since there isn't a target set and as such everything in that if statement should be entirely skipped over. Its kinda driving me nuts.
UPDATE: Alright. As per request, here is the code relevant to targets being assigned.
In the Create Event the target is assigned to noone / undefined with...
target = noone; // The id of the enemy instance this weapon is aiming at.
In the Step Event a potential target, assuming one exists, is checked for with...
// Check if the target still exists and if not then reset target to the default 'noone'
if(target != noone && !instance_exists(target)) then target = noone;
// If there isn't currently a target being aimed at or the weapon is idle then set the target as random or nearest player piece.
if(target == noone && object_exists(obj_player))
{
if(targetting_method = "random")
{
var randtarg = irandom_range(0, ds_list_size(global.segment_list) - 1);
target = ds_list_find_value(global.segment_list, randtarg);
}
if(targetting_method = "nearest")
{
target = instance_nearest(x, y, obj_player);
}
}
Using the debugger while running the program shows the enemy objects target variable as "undefined". So, at least according to the debugger, the target is correctly assigned to noone / undefined at the time the program crashes out by running the code inside that if statement block that should only be run in the event there actually is a target.
UPDATE 2: I had initially stated, just above actually, that the debugger correctly shows my target variable being assigned as "undefined" / noone. This was a mistake on my part and is incorrect.
Its true that with the specific obj_soldier that the game crashed on was showing target as holding the value "undefined". However "undefined" is NOT equal to "noone".
The Gamemaker manual lists that noone is the value of -4 so when you set a variable to hold the value of noone its simply being set to hold -4. So, my obj_soldier having a target of "undefined" means it wasn't properly set as noone.
Since "undefined" is literally not assignment when my if statement tries to check if "target != noone" it passes the if statement check because "undefined" isn't -4. Which causes my if statement to continue on and try to run its checks for when there is actually a target and the end result is that my program tries to do calculations involving "undefined", such as trying to check the obj_soldiers distance to "undefined" which results in a rather expected crash.
Through experimenting I've found that the first obj_soldier I create is correct and works fine. For them target is correctly noone (-4) and they don't crash the game when that if statement runs its check. This occurs whether I place them directly in the room or create them via code.
My second obj_soldier that is created however, doesn't have target assigned correctly and it ends up showing in the debugger as "undefined". When the if statement check occurs they erroneously pass the check and then cause the program to crash doing impossible calculations. This occurs whether the second soldier is placed in the room directly or created via code.
Interestingly, all obj_soldiers after the second work fine and have target correctly noone (-4) just like the first obj_soldier. Place directly or created via code doesn't matter.
For example, if I place or create with code 30 soldiers (which I did several times as a test) the game crashes and in the debugger the second soldier has target with a value of "undefined" while the first and third through thirtieth soldiers have their target shown as holding "-4" which is correct for an assignment of noone.
Aside from the possibility of this issue being a problem with Gamemaker itself, which I've contacted YoYo Games about and am awaiting a response, I can't really track down a reason for it to be occurring.
All of my obj_soldiers should be identical. They are call just instances of that one object and there should be no exceptions to setting "target = noone" for any of them.
I've even gone so far as to try forcibly reseting target to noone at the time of creation by storing obj_soldier in a variable at the time of creation and using "with" to set "target = noone" for each one.
The only workaround I've found is to immediately before my if statement of "if(target != noone)" is run to have this line "if(is_undefined(target)) then target = noone" to ensure that if the value of target is "undefined" it is forced to being noone just before running the check.
While that workaround avoids the crash it doesn't solve the issue of why setting to noone can sometimes result in a value of "undefined" instead of the correct -4 though.
target
is being declared, and how it gets a value \$\endgroup\$undefined
in debugeer may mean that you didn't define/initialize variable?undefined
can be only in very few specific cases, in all other cases that means an error - you done something wrong. Share your project then I can see, because there may be lot of reasons of the error. \$\endgroup\$