Porting MQ2 to ISXEQ problems

Moderator: MacroQuest Developers

kellewic
a lesser mummy
a lesser mummy
Posts: 38
Joined: Tue Jun 08, 2004 2:27 am
Location: AZ

Porting MQ2 to ISXEQ problems

Post by kellewic » Sun May 21, 2006 4:16 pm

I am trying to port all of my old code to ISXEQ with some success. An issue I am having is with a small routine that just opens and closes packs and banks. I've searched here and the ismods forums and looked through the available code samples I could find, but can't find my answer.

Here is the old code:

Code: Select all

Sub OpenPacks
    /declare slotNumber int local

    /for slotNumber 1 to 8
        /if (!${Window[Pack${slotNumber}].Open) {
            /itemnotify pack${slotNumber} rightmouseup
        }
    /next slotNumber
return
here is the new code ('Ive also tried this as an atom):

Code: Select all

function OpenPacks()
{
	variable byte slot

	while (${slot:Inc} <= 8)
	{
		if (!${Window[pack${slot}].Open})
		{
			EQitemnotify pack${slot} rightmouseup
		}
	}
}
I have 4 total functions which are:

OpenPacks
ClosePacks
OpenBanks
CloseBanks

all are very similar to what is posted above (banks uses 1-24). The problem is that sometimes when I run these, they don't open all the packs and sometimes the OpenXXX routines close packs, which is weird since it's checking for the Open state.

I did notice the ISXEQ runs much faster than the MQ2 version. Could it be that the game simply isn't catching all the commands due to them being done too fast? Should I add some waits in there or something?

Thanks.

Lax
We're not worthy!
We're not worthy!
Posts: 3524
Joined: Thu Oct 17, 2002 1:01 pm
Location: ISBoxer
Contact:

Post by Lax » Sun May 21, 2006 4:24 pm

I did notice the ISXEQ runs much faster than the MQ2 version
Pretty sweet huh :)
Could it be that the game simply isn't catching all the commands due to them being done too fast? Should I add some waits in there or something?
Quite possible. Try adding a "waitframe" command after each EQitemnotify. MQ2 has implicit waitframe commands after some operations, and these implicit waits are not present in ISXEQ.
Lax Lacks
Master of MQ2 Disaster
Purveyor of premium, EULA-safe MMORPG Multiboxing Software
* Multiboxing with ISBoxer: Quick Start Video
* EQPlayNice, WinEQ 2.0

kellewic
a lesser mummy
a lesser mummy
Posts: 38
Joined: Tue Jun 08, 2004 2:27 am
Location: AZ

Post by kellewic » Sun May 21, 2006 8:08 pm

Lax wrote:
I did notice the ISXEQ runs much faster than the MQ2 version
Pretty sweet huh :)
Yes it is :) The capability to run multiple scripts...


I am having some crashing issues (you will see several crash reports from me :))

Some weird things... I have an objectdef with Initialize:


Code: Select all

objectdef Inventory
{
       ;This crashes InnerSpace every time
	;variable array packs[8]

	method Initialize()
	{
                ; This works
		;declare packs[8] int Global

                ;This works and I don't know why
                ;declare packs[8] dfdsfds Global

                ;This crashes InnerSpace every time (InvPack is another objectdef
                ;declare packs[8] InvPack Global

		echo Initialized
	}

I think "variable array packs[8]" is wrong syntax, but results in a crash rather than a "compile" time syntax error

I am uncertain why my "declare array[x] ObjectType Global" fails when I use another custom object type. I can give it a completely bogus type (i.e. 'sdfsdfgdfgd') and it does not crash.

Can you provide some insight to these brhaviors? Thanks.

Lax
We're not worthy!
We're not worthy!
Posts: 3524
Joined: Thu Oct 17, 2002 1:01 pm
Location: ISBoxer
Contact:

Post by Lax » Sun May 21, 2006 11:53 pm

You cannot declare an array variable like
variable array packs[8]
but it should also not crash, so I'll look nito that.
It should instead be:
variable InvPack packs[8]

The crash issue in the Initialize method is part of a larger issue -- the script moves out of context because it's trying to abort and issue an error to the console, but the script wants to keep trying to initialize the variable. At the moment it's simply unsafe to error out of a script in an objectdef Initialize because of that problem, and I havent had time to get around to it yet.

The reason it works with a bogus type is because it becomes a string instead, and each element of the packs array should become "dfdsfds Global". The poor DeclareVariable syntax is just another reason why it's better to use variable instead (also, global should not be capitalized).
Lax Lacks
Master of MQ2 Disaster
Purveyor of premium, EULA-safe MMORPG Multiboxing Software
* Multiboxing with ISBoxer: Quick Start Video
* EQPlayNice, WinEQ 2.0

kellewic
a lesser mummy
a lesser mummy
Posts: 38
Joined: Tue Jun 08, 2004 2:27 am
Location: AZ

Post by kellewic » Mon May 22, 2006 1:10 am

Thanks Lax.

One thing I also noticed was that is I have a script with a main

Code: Select all

function main()
{
    ConsoleClear

    variable MyObject obj
}
That the Initialize of MyObject was happening before ConsoleClear. Not sure if this is also part of the issues you speak of, so figured I'd let you know of that behavior.

bardomatic
a ghoul
a ghoul
Posts: 131
Joined: Thu Apr 29, 2004 12:09 am

Post by bardomatic » Mon May 22, 2006 9:09 am

ya, it processes the variables at the beginning of the function regardless of where they are, so keep that in mind when using stuff like variable int myint ${Math.Calc[${othervariable}+3]} it will use the value of othervariable that was available at the moment the function started.

echoism
a ghoul
a ghoul
Posts: 131
Joined: Tue Oct 19, 2004 9:59 am

Post by echoism » Tue May 23, 2006 7:11 am

Code: Select all

objectdef PackHandler
{
	method TogglePack(int myPackID)
	{
		if ${InvSlot[${myPackID}].Item.Container}
			nomodkey EQItemNotify ${myPackID} RightMouseUp
	}

	member IsOpen(myPackID)
	{
		return ${Window[${InvSlot[${myPackID}].Name}].Open}
	}

	function OpenPack(int myslot)
	{
		if ${InvSlot[${myslot}].Pack}
			myslot:Set[${InvSlot[${myslot}].Pack}]
		elseif (${InvSlot[$myslot}].Item.Container} == 0)
			return FALSE
		if !${This.IsOpen[${myslot}]}
		{
			This:TogglePack[${myslot}]
			wait 10 ${This.IsOpen[${myslot}]}
			Wait 1
		}
	}
	
	function ClosePack(int myslot)
	{
		if ${InvSlot[${myslot}].Pack}
			myslot:Set[${InvSlot[${myslot}].Pack}]
		elseif (${InvSlot[$myslot}].Item.Container} == 0)
			return FALSE
		if ${This.IsOpen[${myslot}]}
		{
			This:TogglePack[${myslot}]
			wait 10 !${This.IsOpen[${myslot}]}
			Wait 1
		}
	}
}
I wrote this, but it works strictly off ID numbers, not slot names.
I use that object with this one:

Code: Select all

objectdef ItemHandler inherits PackHandler
{
	variable string Name
	variable int ID
	variable int oldSlot
	variable int tempSlot
	method Initialize(string myname,int myslot)
	{
		Name:Set[${myname}]
		ID:Set[${FindItem[=${myname}].ID}]
		if !${myslot}
			tempSlot:Set[29]
		else
			tempSlot:Set[${myslot}]
		
	}
	member PackID=${FindItem[=${This.Name}].InvSlot.Pack}
	member Stackable=${FindItem[=${This.Name}].Stackable}
	member CastTime=${FindItem[=${This.Name}].CastTime}
	member Pack=${FindItem[=${This.Name}].InvSlot.Pack.Name}
	member Slot=${FindItem[=${This.Name}].InvSlot}
	member Count=${FindItemCount[=${This.Name}]}
	member IsPackOpen=${Window[${This.Pack}].Open}
	method LeftClick(myslot,mymod)
	{
		if !${myslot}
			myslot:Set[${This.Slot}]
		if !${mymod.Length}
			mymod:Set[nomodkey]
		else
			mymod:Set[${mymod] nomodkey]
		Execute "${mymod} EQItemNotify ${myslot} LeftMouseUp"
	}
	method RightClick(myslot)
	{
		if !${myslot}
			myslot:Set[${This.Slot}]
		nomodkey EQItemNotify ${myslot} RightMouseUp
	}

	function PickUp(string qty)
	{
		variable string mod
		if ${Cursor.ID}
			return FALSE
		Switch ${qty}
		{
			case ctrl
			case single
			case 1
				mod:Set[ctrl]
				break
			case 20
			case all
			case stack
			case shift
				mod:Set[shift]
				break
			default
				if ${This.Stackable}
					mod:Set[ctrl]
		}
		oldSlot:Set[${This.Slot}]
		call This.CursorToggle ${This.Slot} ${mod}
	}

	function PutDown(int destSlot)
	{
		if ${Cursor.ID} != ${This.ID}
			return FALSE
		if !${destSlot}
			destSlot:Set[${This.oldSlot}]
		call This.CursorToggle ${destSlot}
	}

	function CursorToggle(int myslot,string mymod)
	{
		if !${myslot}
			myslot:Set[${This.Slot}]
		if !${myslot}
			myslot:Set[${This.oldSlot}]
		variable int OldCursorID=${Cursor.ID}
		call This.OpenPack ${myslot}
		This:LeftClick[${myslot},${mymod}]
		wait 50 (${OldCursorID} != ${Cursor.ID}
		call This.ClosePack ${myslot}
	}

	function MoveTo(string myslot,string mymod)
	{
		call This.PickUp ${mymod}
		call This.PutDown ${myslot}
	}
	
	function Activate()
	{
		if ${This.Busy}
			return FALSE
		variable bool SwapFlag=FALSE
		if (${Cursor.ID} || ${This.Count}==0)
			return FALSE
		if ${This.Slot} > 29
			SwapFlag:Set[TRUE]
		if ${SwapFlag}
			call This.MoveTo ${tempSlot}
		This:RightClick
		if ${This.CastTime}
		{
			Wait 10 ${Me.Casting.ID}
			while ${Me.Casting.ID}
				WaitFrame
		}
		if ${SwapFlag}
		{
			if ${Cursor.ID} && ${InvSlot[${tempSlot}].Item.ID}== ${This.ID}
				call This.CursorToggle ${tempSlot}
			call This.PutDown ${oldSlot}
		}
	}
	member:bool Busy()
	{
		if ( ${Cursor.ID} || ${Me.Casting.ID} || ${Window[MerchantWnd].Open} || ${Window[SpellBookWnd].Open} || ${Window[TradeWnd].Open} || ${Window[BigBankWnd].Open} || ${Window[BankWnd].Open} || ${Window[LootWnd].Open} )
				return TRUE
		else 
				return FALSE
	}
}
to handle my items.
Granted, this is only until I add a real InvSlot:MoveTo method to the source, but this gets me by for now.

e.g.

Code: Select all

function main()
{
	declare myitem ItemHandler script "Iron Ration"
	call myitem.Activate
}
Would find an item named "Iron Ration" in your inventory, check to make sure none of the windows listed in the Busy function are open, and check your cursor for items, then it would swap it (defaulting to one item if stackable) to its tempslot (defaults to pack8, can be set with 2nd parameter in declare), if its an item clicky, it'll wait for the item to finish casting before swapping it back.

echoism
a ghoul
a ghoul
Posts: 131
Joined: Tue Oct 19, 2004 9:59 am

Post by echoism » Tue May 23, 2006 7:13 am

Quite possible. Try adding a "waitframe" command after each EQitemnotify. MQ2 has implicit waitframe commands after some operations, and these implicit waits are not present in ISXEQ.
I found that Waitframe was too fast for inventory containers to open/close. bags get reported as open before you can actually click on anything inside them, so I had to use Wait 1, instead of Waitframe.

Lax
We're not worthy!
We're not worthy!
Posts: 3524
Joined: Thu Oct 17, 2002 1:01 pm
Location: ISBoxer
Contact:

Post by Lax » Tue May 23, 2006 11:07 am

The variable keyword creates and initializes variables as part of script structure -- it is not a command that is executed in sequence like DeclareVariable is. Any variables declared with the variable keyword are created in the order received, and as soon as they enter scope -- e.g. as soon as the script runs, the global/globalkeep/script scopes are set up, and as soon as a function loads, its local scope is set up.

Code: Select all

function main()
{
  echo ${i},${j},${k}

  variable int k=${j}
  variable int i=1
  variable int j=${i}
}
In the above function, the echo will be 1,1,0. The variable line for k is effectively "variable int k=NULL" which will of course be 0.
Lax Lacks
Master of MQ2 Disaster
Purveyor of premium, EULA-safe MMORPG Multiboxing Software
* Multiboxing with ISBoxer: Quick Start Video
* EQPlayNice, WinEQ 2.0

kellewic
a lesser mummy
a lesser mummy
Posts: 38
Joined: Tue Jun 08, 2004 2:27 am
Location: AZ

Post by kellewic » Wed May 24, 2006 7:03 pm

Lax wrote:You cannot declare an array variable like
variable array packs[8]
but it should also not crash, so I'll look nito that.
It should instead be:
variable InvPack packs[8]

The crash issue in the Initialize method is part of a larger issue -- the script moves out of context because it's trying to abort and issue an error to the console, but the script wants to keep trying to initialize the variable. At the moment it's simply unsafe to error out of a script in an objectdef Initialize because of that problem, and I havent had time to get around to it yet.
So with the correct syntax Initialize should be fine and not crash? Reason I ask, is because the following will still crash InnerSpace every time:

Code: Select all

objectdef Inventory
{
	method Initialize()
	{
		variable InvPack packs[8]
		variable byte slot

		echo Initialized
	}
}
Where InvPack is another objectdef, but has no Initialize (not sure if that matters any).

I can't find any examples in other code where anyone is trying to create an array of objectdef types so I can verify I am not doing something stupid :)

Also, the following causes a crash as well... seems to be arrays of objectdef items:

Code: Select all

objectdef Inventory
{
	variable InvPack packs[8]

	member ToText()
	{
		return Inventory Text
	}
}
If I remove the variable def, it works just fine.

Lax
We're not worthy!
We're not worthy!
Posts: 3524
Joined: Thu Oct 17, 2002 1:01 pm
Location: ISBoxer
Contact:

Post by Lax » Wed May 24, 2006 7:30 pm

Reason I ask, is because the following will still crash InnerSpace every time
Does the Lavish crash reporter come up? If you submit a crash report I can fix whatever problem it is much quicker ;)

I presume you havent done so, but I just did it myself for a good crash anyway, so I'll get it fixed.
Lax Lacks
Master of MQ2 Disaster
Purveyor of premium, EULA-safe MMORPG Multiboxing Software
* Multiboxing with ISBoxer: Quick Start Video
* EQPlayNice, WinEQ 2.0

Lax
We're not worthy!
We're not worthy!
Posts: 3524
Joined: Thu Oct 17, 2002 1:01 pm
Location: ISBoxer
Contact:

Post by Lax » Wed May 24, 2006 7:53 pm

Build 3997 fixes this array issue
Lax Lacks
Master of MQ2 Disaster
Purveyor of premium, EULA-safe MMORPG Multiboxing Software
* Multiboxing with ISBoxer: Quick Start Video
* EQPlayNice, WinEQ 2.0

kellewic
a lesser mummy
a lesser mummy
Posts: 38
Joined: Tue Jun 08, 2004 2:27 am
Location: AZ

Post by kellewic » Wed May 24, 2006 8:18 pm

Lax wrote:
Reason I ask, is because the following will still crash InnerSpace every time
Does the Lavish crash reporter come up? If you submit a crash report I can fix whatever problem it is much quicker ;)

I presume you havent done so, but I just did it myself for a good crash anyway, so I'll get it fixed.
Yeah, I submitted like the first 3, but after that I stopped submitting them so I wouldn't spam you :)

Oh, can you clarify for me that arrays are '1' based and not '0'? (It seems this is the case)

Thanks.

Lax
We're not worthy!
We're not worthy!
Posts: 3524
Joined: Thu Oct 17, 2002 1:01 pm
Location: ISBoxer
Contact:

Post by Lax » Wed May 24, 2006 8:48 pm

Yes, everything similar in LavishScript (and MQ2 for that matter) is 1-based
Lax Lacks
Master of MQ2 Disaster
Purveyor of premium, EULA-safe MMORPG Multiboxing Software
* Multiboxing with ISBoxer: Quick Start Video
* EQPlayNice, WinEQ 2.0

xyilla
naggy
naggy
Posts: 29514
Joined: Sun Feb 23, 2025 5:36 am

Re: Porting MQ2 to ISXEQ problems

Post by xyilla » Sat Jul 12, 2025 9:48 am