Jump to content
Sign in to follow this  
Alex116

Error Zero Divisor, Multi-Dimensional array

Recommended Posts

Hey,

First of all, I've been wanderin these forums and the entire internet for a solution. I've become alot wiser regarding array's though not just wise enough.

The problem I have is that I'm running a script from a .sqf file. This .sqf file is a multi dimensional array. The script it fires up uses _pos = _this select 1;.

If then requests the element from the previous script which is an multi dimensional array and it gets an error message saying "Erro Zero Divisor" because

the value it returned couldn't be divided by 0?

Im confused here and I'm sure you are too after the above story so let me show you some scripts.

I created a custom radio channel which has a sub channel. This is the subchannel's SQF.

menu.sqf

QUADsub = [
 ["REQUEST AIRDROP",true],
 ["AIRDROP OPTIONS", [0],"",-2,[["expression", ""]], "1", "1"], // header text 
 ["ATV"         ,[2],"",-5,[["expression","[] execVM 'comm.sqf'"]],"1","1"],
 ["ATV"         ,[3],"",-5,[["expression","[] execVM 'comm.sqf'"]],"1","1"]
];  

As you can see it has two options, both called ATV. When selecting either one of them it would fire up comm.sqf.

//////////////////////////////////////////////////////////////////
// Function file for Armed Assault
// Created by: TODO: Author Name
//////////////////////////////////////////////////////////////////

_caller = _this select 0;
_pos =  _this select 1;
_target = _this select 2;
_is3D = _this select 3;
_id = _this select 4;

_data= [_caller, _id];

/*
if (isMultiplayer) then
{
[
	_data,
	"BIS_fnc_removeCommMenuItem",
	true,
	false
] spawn BIS_fnc_MP;
};
*/

_startPos = 
[
_pos select 0,
_pos select 1,
(_pos select 2) + 300
];

_apc= "B_APC_Wheeled_01_cannon_F" createVehicle _startPos;
_apc setPos [
_startPos select 0,
_startPos select 1,
_startPos select 2
];
sleep 0.5;

_para= "B_Parachute_02_F";
_chute= _para createVehicle (getPos _apc);

_chute setPos [
getPos _apc select 0,
getPos _apc select 1,
getPos _apc select 2
];

_chute attachTo [_apc, [0,0,0]];
sleep 2;
detach _chute;
_apc attachTo [_chute, [0,0,0]];

if (surfaceIsWater (getPos _apc)) then {
waitUntil 
{
	((getPosASL _apc) select 2) < 3
};
detach _apc;
sleep 2;
_apc setVectorUp [0,0,1];
} else {
waitUntil 
{
	((getPos _apc) select 2) < 3
};
detach _apc;
waitUntil {isTouchingGround _apc};
sleep 2;
_apc setVectorUp [0,0,1];
};

Now the error I'm getting is the Error Zero Divisor for line 7. (_pos = _this select 1; )

Now I'm guessing that the variables defined on line 8, 9, and 10 would do the same.

I'm new to this but if I'm correct it gives me this error because of this:

Player calls for ATV.

Player is known as _this in the first script. (menu.sqf)

Menu.sqf opens a second script comm.sqf

Player is no longer known as _this in this script.

Script tries to get player position by using _this but doesnt work so I get an error.

I would really love to know what causes this error and how I could solve this in this example and in the future.

Sincerely,

Alex

Share this post


Link to post
Share on other sites

The reason you have an "Error Zero Divisor" error is because you're trying to select an element that doesn't exist. I think I may be able to help you but I need a little more information:

Player calls for ATV. //Okay, granted.
Player is known as _this in the first script. (menu.sqf) //can you show me how menu.sqf is being called?
Menu.sqf opens a second script comm.sqf //I assume you have some code that selects the element and then runs some code to start the script, please post that
Player is no longer known as _this in this script. //Gonna have to take your word for it until I see the rest of the code
Script tries to get player position by using _this but doesnt work so I get an error.

EDIT: And before you change anything, put a hint at the top of your script and post the output

Change:

_caller = _this select 0;
_pos =  _this select 1;
_target = _this select 2;
_is3D = _this select 3;
_id = _this select 4;

_data= [_caller, _id];

To:

hint str _this;
copyToClipboard _this; //DO NOT COPY ANYTHING NOW, you will erase what's saved in your clipboard. When you write your new post, just press ctrl + v to paste the output (which would be your scripts input)

_caller = _this select 0;
_pos =  _this select 1;
_target = _this select 2;
_is3D = _this select 3;
_id = _this select 4;

_data= [_caller, _id];

Edited by DreadedEntity

Share this post


Link to post
Share on other sites

Thanks for taking the time to help me out.

The trigger that activates the radio menu.

quaddrop = [p1,"Quad"] call BIS_fnc_addCommMenuItem;

The description.ext which holds the radio menu.

class CfgCommunicationMenu
{
class QUAD
{
text = "REQUEST AIRDROP"; // Text displayed in the menu and in a notification
submenu = "#USER:QUADsub"; // Submenu opened upon activation (expression is ignored when submenu is not empty.)
expression = ""; // Code executed upon activation
icon = "\a3\Ui_f\data\GUI\Cfg\CommunicationMenu\supplydrop_ca.paa"; // Icon displayed permanently next to the command menu
cursor = "\a3\Ui_f\data\IGUI\Cfg\Cursors\iconCursorSupport_ca.paa"; // Custom cursor displayed when the item is selected
enable = "1"; // Simple expression condition for enabling the item
removeAfterExpressionCall = 1; // 1 to remove the item after calling
};
};

The submenu script it calls. (menu.sqf)

QUADsub = [
 ["REQUEST AIRDROP",true],
 ["AIRDROP OPTIONS", [0],"",-2,[["expression", ""]], "1", "1"], // header text 
 ["ATV"         ,[2],"",-5,[["expression","[] execVM 'comm.sqf'"]],"1","1"],
 ["ATV"         ,[3],"",-5,[["expression","[] execVM 'comm.sqf'"]],"1","1"]
];  

The comm.sqf file that menu.sqf fires.

//////////////////////////////////////////////////////////////////
// Function file for Armed Assault
// Created by: TODO: Author Name
//////////////////////////////////////////////////////////////////

_caller = _this select 0;
_pos =  _this select 1;
_target = _this select 2;
_is3D = _this select 3;
_id = _this select 4;

_data= [_caller, _id];

/*
if (isMultiplayer) then
{
[
	_data,
	"BIS_fnc_removeCommMenuItem",
	true,
	false
] spawn BIS_fnc_MP;
};
*/

_startPos = 
[
_pos select 0,
_pos select 1,
(_pos select 2) + 300
];

_apc= "B_APC_Wheeled_01_cannon_F" createVehicle _startPos;
_apc setPos [
_startPos select 0,
_startPos select 1,
_startPos select 2
];
sleep 0.5;

_para= "B_Parachute_02_F";
_chute= _para createVehicle (getPos _apc);

_chute setPos [
getPos _apc select 0,
getPos _apc select 1,
getPos _apc select 2
];

_chute attachTo [_apc, [0,0,0]];
sleep 2;
detach _chute;
_apc attachTo [_chute, [0,0,0]];

if (surfaceIsWater (getPos _apc)) then {
waitUntil 
{
	((getPosASL _apc) select 2) < 3
};
detach _apc;
sleep 2;
_apc setVectorUp [0,0,1];
} else {
waitUntil 
{
	((getPos _apc) select 2) < 3
};
detach _apc;
waitUntil {isTouchingGround _apc};
sleep 2;
_apc setVectorUp [0,0,1];
};

I do not recieve anything on my clipboard. It gives me another error "Error copytoclipboard: Type Array expected String"

Also the script (comm.sqf) does work when you fire the script from the CfgCommunicationMenu in the description.ext.

If you execute the command from the expression line and leave the submenu line empty.

But as you might expect I rather do have a submenu and a solution to this error.

Share this post


Link to post
Share on other sites

I made a mistake

copyToClipboard _this;
//SHOULD BE
copyToClipboard str _this;

Also, I didn't know you were using the comm menu, that would have been nice to know. I've never used it before. But from the wiki page:

  • caller: Object - unit which called the item, usually player
  • pos: Array in format Position - cursor position
  • target: Object - cursor target
  • is3D: Boolean - true when in 3D scene, false when in map
  • ID: String - item ID as returned by BIS_fnc_addCommMenuItem function

My assumption is that you weren't pointing at the ground when you called for the support. This might be proved after you post the clipboard, which should show everything that the script knows about. If not, I guess I'll need to have a play with this myself and figure it out

Share this post


Link to post
Share on other sites

Still, all it copies is: "[]". And im definitely pointing at the ground.

What I find strange is that it does work when not being fired from out of a submenu.While it does work when fired from the expression line in the CfgCommunicationsMenu.

It appears to me that it cant reach the element array (the position your looking at) because its tangled up or got lost in the menu.sqf

Isn't there a way for the comm.sqf script to look for that element himself? Or have it made a global variable inside menu.sqf?

Share this post


Link to post
Share on other sites

Your not passing the information to your script from the expression...

["expression","[] execVM 'comm.sqf'"]

Should be...

["expression","[_caller,_pos,_target,_is3D,_ID] execVM 'comm.sqf'"]

WIKI:

Expression Arguments

Following arguments are passed into the expression field:

[caller,pos,target,is3D,ID]

caller: Object - unit which called the item, usually player

pos: Array in format Position - cursor position

target: Object - cursor target

is3D: Boolean - true when in 3D scene, false when in map

ID: String - item ID as returned by BIS_fnc_addCommMenuItem function

This is a set of variables that are available inside the expression field and need passing to your script for you to be able to access them there.

Share this post


Link to post
Share on other sites

Thanks a lot. I cant believe I oversaw that.

It works now. Though I still get an error message.

In line 14 of comms.sqf (undefined variable in expression: _caller)

Caller is defined right? Just at the beginning.

Share this post


Link to post
Share on other sites

Also, one more related question.

Let's say I have an object (intell documents) that runs a script when picked up.

Object init:

   if (isServer) then { execVM "sdocs.sqf" };

sdocs.sqf:


if (isServer) then {
   this setVariable ["RscAttributeDiaryRecord_texture","a3\structures_f_epc\Items\Documents\Data\document_secret_01_co.paa", true];
   [this,"RscAttributeDiaryRecord",["Top Secret Docs","These Docs outline the enemies defenses",""]] call bis_fnc_setServerVariable;
   this setVariable ["recipients", west, true];
   ["Task2","Extraction","Get to teh choppa!"] call SHK_Taskmaster_add;
   ["Task1","succeeded","Task2"] call SHK_Taskmaster_upd;
};  

It gives me an error saying that"this" is an undefined variable. How do I use variables to define an object so it is recognised by the script.

I've read the wiki page about this and more, though it doesnt get trough to me.

When I use the debug console to getvariable on the object it returns me the following:

[[Control #1],0]

What does this mean?

Edited by Alex116

Share this post


Link to post
Share on other sites

Use this as your call to the script:

[this] execVM "script.sqf";

In your actual code, there is no need for another if (isServer) check, and add the following and replace all your instances of "this" with "_obj":

_obj = (_this select 0);

Share this post


Link to post
Share on other sites
It gives me an error saying that "this" is an undefined variable. How do I use variables to define an object so it is recognised by the script.

I've read the wiki page about this and more, though it doesnt get trough to me.

"this" only works in the init lines of objects, you need to pass that data to the script in order for it to work and use "_this" inside the script

if (isServer) then { /*this execVM "sdocs.sqf"*/ };

if (isServer) then {
   /*_this*/ setVariable ["RscAttributeDiaryRecord_texture","a3\structures_f_epc\Items\Documents\Data\document_secret_01_co.paa", true];
   [/*_this*/,"RscAttributeDiaryRecord",["Top Secret Docs","These Docs outline the enemies defenses",""]] call bis_fnc_setServerVariable;
   /*_this*/ setVariable ["recipients", west, true];
   ["Task2","Extraction","Get to teh choppa!"] call SHK_Taskmaster_add;
   ["Task1","succeeded","Task2"] call SHK_Taskmaster_upd;
};

I made the parts I edited into comments (so you can easily see what I've done), just make sure you remove the comment markers ( /* */ ) before running the code, or else you'll get a shitload of errors (probably)

Share this post


Link to post
Share on other sites

Thanks, I slowly start to understand. Once again, thank you guy's for helping out.

I still cant seem to get rid of the other error though.

Thanks a lot. I cant believe I oversaw that.

It works now. Though I still get an error message.

In line 14 of comms.sqf (undefined variable in expression: _caller)

Caller is defined right? Just at the beginning.

Since _caller is defined.

Share this post


Link to post
Share on other sites

It may be that the object passed into the script (_this select 0) is null or dead, could you provide your call line for that script again, assuming you did as Larrow recommened a few posts back.

Share this post


Link to post
Share on other sites

QUADsub = [
 ["REQUEST AIRDROP",true],
 ["AIRDROP OPTIONS", [0],"",-2,[["expression", ""]], "1", "1"], // header text 
 ["ATV"         ,[2],"",-5,[["expression","[_caller,_pos,_target,_is3D,_ID] execVM 'comm.sqf'"]],"1","1"],
 ["ATV"         ,[3],"",-5,[["expression","[_caller,_pos,_target,_is3D,_ID] execVM 'comm.sqf'"]],"1","1"]
];

Is it like tangled up in the above code of array's that it cant find it?

Share this post


Link to post
Share on other sites

How is "_caller" being defined before QUADsub?

Share this post


Link to post
Share on other sites

It's not. That's the entire script. Same goes for "_pos", "_target","_is3D" and "_ID".

So these all need to be defined, correct? So how does one do that?

Trough the "_caller = (_this select 0);" line? How do I know if it's select 0/1/2/3?

Share this post


Link to post
Share on other sites

Yes, of course it needs to be defined, and I can't answer how to do that because I don't have enough context of what all your doing to be able to help you define each of those variables.

In regards on how to decide where to use select 0/1/2/3 Google "Arrays in Arma 3" and that wiki page should answer your questions.

Share this post


Link to post
Share on other sites

I see, so by selecting either 0/1/2/3 you select an array, the value of that array.

Well, I've basicly created a custom radio channel, with another sub-menu. Now when you select option 1 or 2, it will execute comm.sqf.

Though the sub-menu script requests the following expression arguments ;

Arma 3 Communication Menu

Expression Arguments

Following arguments are passed into the expression field:

[caller,pos,target,is3D,ID]

caller: Object - unit which called the item, usually player

pos: Array in format Position - cursor position

target: Object - cursor target

is3D: Boolean - true when in 3D scene, false when in map

ID: String - item ID as returned by BIS_fnc_addCommMenuItem function

So to define caller, I would have to define the player that selected the option. How does one do that?

Share this post


Link to post
Share on other sites

Ok, sorry from me not actually reading this thread completely, but back to it, from what I understand from that page, where you currently have the call to the script try something more like this (I've never used the comms menu cfg before):

["expression","[_caller,_pos,_target,_is3D,_ID] execVM comms.sqf"]

But like I said I haven't used this, and the wiki page is a bit unclear on how it's used...

Share this post


Link to post
Share on other sites

Mhmm. Which makes it this:

QUADsub = [
 ["REQUEST AIRDROP",true],
 ["AIRDROP OPTIONS", [0],"",-2,[["expression", ""]], "1", "1"], // header text 
 ["ATV"         ,[2],"",-5,[["expression","[_caller,_pos,_target,_is3D,_ID] execVM comms.sqf"]],"1","1"],
 ["ATV"         ,[3],"",-5,[["expression","[_caller,_pos,_target,_is3D,_ID] execVM comms.sqf"]],"1","1"]
];  

And gives me an "Error missing;".

Share this post


Link to post
Share on other sites

Sorry, forgot the single quotes around 'comms.sqf'

Share this post


Link to post
Share on other sites

Still gives me the error; "undefined variable in expression _caller". Line 12.

//////////////////////////////////////////////////////////////////
// Function file for Armed Assault
// Created by: TODO: Author Name
//////////////////////////////////////////////////////////////////

_caller = _this select 0;
_pos =  _this select 1;
_target = _this select 2;
_is3D = _this select 3;
_id = _this select 4;

_data = [_caller, _id];


if (isMultiplayer) then
{
[
	_data,
	"BIS_fnc_removeCommMenuItem",
	true,
	false
] spawn BIS_fnc_MP;
};


_startPos = 
[
_pos select 0,
_pos select 1,
(_pos select 2) + 300
];

_apc= "B_APC_Wheeled_01_cannon_F" createVehicle _startPos;
_apc setPos [
_startPos select 0,
_startPos select 1,
_startPos select 2
];
sleep 0.5;

_para= "B_Parachute_02_F";
_chute= _para createVehicle (getPos _apc);

_chute setPos [
getPos _apc select 0,
getPos _apc select 1,
getPos _apc select 2
];

_chute attachTo [_apc, [0,0,0]];
sleep 2;
detach _chute;
_apc attachTo [_chute, [0,0,0]];

if (surfaceIsWater (getPos _apc)) then {
waitUntil 
{
	((getPosASL _apc) select 2) < 3
};
detach _apc;
sleep 2;
_apc setVectorUp [0,0,1];
} else {
waitUntil 
{
	((getPos _apc) select 2) < 3
};
detach _apc;
waitUntil {isTouchingGround _apc};
sleep 2;
_apc setVectorUp [0,0,1];
};

Which is strange because even though it gives me this error, the script still fires and spawn a vehicle where I point.

So I don't think theres a problem with the expressions.

Also the _data is only used in this piece of the script.

_data = [_caller, _id];


if (isMultiplayer) then
{
[
	_data,
	"BIS_fnc_removeCommMenuItem",
	true,
	false
] spawn BIS_fnc_MP;
};

Is this piece really needed to ensure MP compability? Seems a strange piece of code to me.

---------- Post added at 05:56 ---------- Previous post was at 05:03 ----------

"this" only works in the init lines of objects, you need to pass that data to the script in order for it to work and use "_this" inside the script

if (isServer) then { /*this execVM "sdocs.sqf"*/ };

if (isServer) then {
   /*_this*/ setVariable ["RscAttributeDiaryRecord_texture","a3\structures_f_epc\Items\Documents\Data\document_secret_01_co.paa", true];
   [/*_this*/,"RscAttributeDiaryRecord",["Top Secret Docs","These Docs outline the enemies defenses",""]] call bis_fnc_setServerVariable;
   /*_this*/ setVariable ["recipients", west, true];
   ["Task2","Extraction","Get to teh choppa!"] call SHK_Taskmaster_add;
   ["Task1","succeeded","Task2"] call SHK_Taskmaster_upd;
};

I made the parts I edited into comments (so you can easily see what I've done), just make sure you remove the comment markers ( /* */ ) before running the code, or else you'll get a shitload of errors (probably)

Also, regarding the other piece of code. If I use DreadedEntity's code above it tells me call SHK_Taskmaster_add; is an undefined variable in expression.

I've tried using this variable from an objects initialization field and that does the trick. Though theres got to be away to define this variable.

Now the problem I have with defining this, is that its part of a function. It's an inline function located in another SQF. How does one define that in another SQF?

Edited by Alex116

Share this post


Link to post
Share on other sites

Right

[_caller, _pos, _target, _is3D, _ID] are magic variables passed into the expression by the comm menu system. What i posted before and what JShock has reposted is the correct way of passing these variables from the expression to your script.

From a quick test _caller and _id do not seem to work, whether this is because it is from a sub menu or not i did not test. All other variables are ok.

description.ext

class CfgCommunicationMenu
{
class QUAD
{
	text = "REQUEST AIRDROP"; // Text displayed in the menu and in a notification
	submenu = "#USER:QUADsub"; // Submenu opened upon activation
	icon = "\a3\Ui_f\data\GUI\Cfg\CommunicationMenu\supplydrop_ca.paa"; // Icon displayed permanently next to the command menu
	enable = "1"; // Menu item is available
};
};

I have removed the cursor as it did not make sense to have a position selection cursor here, its not really needed until your actually selecting a drop.

init.sqf

QUADsub = [
 ["REQUEST AIRDROP",true],
 ["AIRDROP OPTIONS", [0],"",-2,[["expression", ""]], "1", "0"], // 0 so its not selectable
 ["ATV", [2], "", -5, [ [ "expression", "[_pos] execVM 'comm.sqf'" ] ], "1", "CursorOnGround", "\a3\Ui_f\data\IGUI\Cfg\Cursors\iconCursorSupport_ca.paa"]
];

//Function to remove ATV drop support call for multiplayer clients
My_removeCommMenuItem = {
_id = player getVariable [ "quaddrop", nil ];
if ( !( isNil "_id" )  ) then {
	[ player, _id ] call BIS_fnc_removeCommMenuItem;
};
};

//For testing
player addAction ["comms", { player setVariable [ "quaddrop", [ player, "Quad" ] call BIS_fnc_addCommMenuItem ]; }];

I have added a function here to allow your multiplayer part of comm.sqf to work see further down. Also added selection cursor to ATV menu item. Made AIRDROP OPTIONS not selectable so it acts as a header.

Take note of my addaction for applying the comms menu. It sets a variable on the player to allow us to remove the menu item later. This is something you will need to apply to your trigger.

comm.sqf

//////////////////////////////////////////////////////////////////
// Function file for Armed Assault
// Created by: TODO: Author Name
//////////////////////////////////////////////////////////////////

_pos =  _this select 0;

[ player, player getVariable "quaddrop" ] call BIS_fnc_removeCommMenuItem;

if (isMultiplayer) then
{
   [
       [],
       "My_removeCommMenuItem",
       true,
       false
   ] spawn BIS_fnc_MP;
};


_startPos = _pos vectorAdd [ 0, 0, 300 ];

_apc = createVehicle [ "B_APC_Wheeled_01_cannon_F", _startPos, [], 0, "NONE" ];
_apc setPosATL _startPos;
sleep 0.5;

_chute= createVehicle [ "B_Parachute_02_F", (getPos _apc), [], 0, "CAN_COLLIDE" ];
_chute setPosATL getPosATL _apc;

_apc attachTo [_chute, [0,0,0]];

if (surfaceIsWater (getPosASL _apc)) then {
   waitUntil { ((getPosASL _apc) select 2) < 3 };
   detach _apc;
   sleep 2;
   _apc setVectorUp [0,0,1];
} else {
   waitUntil { ((getPosATL _apc) select 2) < 3 };
   detach _apc;
   waitUntil {isTouchingGround _apc};
   _apc setVectorUp [0,0,1];
};

_pos is the only thing we need out of the menu.

If someone is calling this then they are going to be the local player so i have just used player for the reference.

If we are in a multiplayer game then our new function in the init is called for everyone that removes the comms item. I presume this is because your trigger is appling it to who ever is in it but you only want to allow A ATV to be available.

Changed your createVehicle and getPos commands to their faster equivalents.

Used vectorAdd rather than the old way of splitting the position array.

Given it a quick test from the editor and all seems ok, let us know how you get on.

Edited by Larrow
spelling

Share this post


Link to post
Share on other sites

Thanks a bunch for the code provided and your explenation, it starts to make sense.

It does work now but with the error;

"[bIS_fnc_removeCommMenuItem] Item -1 not found in the comm menu".

Share this post


Link to post
Share on other sites

This error most likely occurs because the player variable "quaddrop" is not being found so nil is being passed as the ID to BIS_fnc_removeCommMenuItem, can you show me how you have implemented your call to BIS_fnc_addCommMenuItem from your trigger.

As per my note in my previous post...

Take note of my addaction for applying the comms menu. It sets a variable on the player to allow us to remove the menu item later. This is something you will need to apply to your trigger.
Edited by Larrow

Share this post


Link to post
Share on other sites

Aha!

What I did is, copy;

//For testing
player addAction ["comms", { player setVariable [ "quaddrop", [ player, "Quad" ] call BIS_fnc_addCommMenuItem ]; }];  

into my trigger's init box. Hence the error.

After your hint, I edited it and made it;

 player setVariable [ "quaddrop", [ player, "Quad" ] call BIS_fnc_addCommMenuItem ];

And all works fine, once the trigger is activated I get the comms menu. With submenu and upon selecting option 1 the vehicle spawns fine.

Now if I'd like to remove the option from a player I would simply put this in a trigger?;

[ player, player getVariable "quaddrop" ] call BIS_fnc_removeCommMenuItem;

___________________________

Edited by Alex116

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×