Array-based UseInventory doesn't work online.

Discuss all aspects related to modding Zandronum here.
Post Reply
Laggy Blazko
Forum Regular
Posts: 296
Joined: Tue Jun 05, 2012 3:00 pm
Location: Heck no

Array-based UseInventory doesn't work online.

#1

Post by Laggy Blazko » Mon Jan 15, 2018 9:11 pm

https://www.dropbox.com/s/bfpzhadb2rard ... v.pk3?dl=1
Putting this here because I don't know if I messed up or this is a zandro bug, in which case I'll post this in the tracker as well.

This pk3 requires HeXen. A key needs to be bound to activate an inventory menu, displaying all useable items in your inventory. The same key deactivates it. Pressing fire uses the item, which doesn't work online properly for some reason. Using flechettes spawns invisible flechettes, torches don't work and maulotaurs desync, to name a few weird things.

There are 2 CLIENTSIDE scripts. An array is initialized with inventory item names. This is done using a serverside OPEN script. Since the client needs to have access to that array as well, an ENTER CLIENTSIDE script waits 1 tic, check if it's being called by the server (which only should happen offline) and initializes it for the client otherwise. The other CLIENTSIDE script is the inventory menu, which selects items and pukes a NET script using the item's index. According to the debugging I've done, both client and server know what item is occupying said index, but the UseInventory function in the NET script seems to desync.

User avatar
arkore
Forum Regular
Posts: 183
Joined: Mon Dec 17, 2012 8:01 pm

Re: Array-based UseInventory doesn't work online.

#2

Post by arkore » Wed Jan 17, 2018 3:36 pm

It's tough for people to help, so you must make it easier for them. You must put more effort into your question. Please show your work in the form of pasted code (and remove all unnecessary code), youtube video with annotations, etc. and not a pk3.

Laggy Blazko
Forum Regular
Posts: 296
Joined: Tue Jun 05, 2012 3:00 pm
Location: Heck no

Re: Array-based UseInventory doesn't work online.

#3

Post by Laggy Blazko » Mon Jan 22, 2018 1:22 am

I can't make videos but I hope this helps.
Spoiler: code (Open)

Code: Select all

#library "invent"
#include "zcommon.acs"


#define SLOT_ROWS 8		//Number of rows in the inventory interface.
#define SLOT_COLUMNS 8	//Number of columns in the inventory interface.

#define SLOT_MAXROWS 64 //A scrolling system will be implemented in the future.



bool iAmServer;			//It's true for the server and singleplayer games.
str inventory_names[SLOT_COLUMNS*SLOT_MAXROWS]; //Contains inventory item names.
str inventory_icons[SLOT_COLUMNS*SLOT_MAXROWS]; //Contains inventory item icons.

int inventory_names_size; //Number of items currently registered.




//Returns the last inventory index and increases it.
function int requestInventoryNumber (void)
{
	if (inventory_names_size < SLOT_COLUMNS*SLOT_MAXROWS) return inventory_names_size++;
	//Else
	printbold(s:"TOO MANY REGISTERED ITEMS!!! Increase SLOT_MAXROWS!");
	return -1;
	
}


//Registers an item by its name and icon.
function void registerItem (str itemName, str itemIcon)
{
	int invNum = requestInventoryNumber();
	if (invNum != -1)
	{
		inventory_names[invNum] = itemName;
		inventory_icons[invNum] = itemIcon;
	}
}

//List of items to be registered.
function void itemList(void)
{
inventory_names_size = 0;
	registerItem ("ArtiBlastRadius", "ARTIBLST");
	registerItem ("ArtiFly", "ARTISOAR");
	registerItem ("ArtiBoostArmor", "ARTIBRAC");
	registerItem ("ArtiBoostMana", "ARTIBMAN");
	registerItem ("ArtiDarkServant", "ARTISUMN");
	registerItem ("ArtiHealingRadius", "ARTIHRAD");
	registerItem ("ArtiHealth", "ARTIPTN2");
	registerItem ("ArtiInvulnerability2", "ARTIDEFN");
	registerItem ("ArtiTorch", "ARTITRCH");
	registerItem ("ArtiPoisonBag", "ARTIPSBG");
	registerItem ("ArtiPoisonBag1", "ARTIPSBG");
	registerItem ("ArtiPoisonBag2", "ARTIPSBG");
	registerItem ("ArtiPoisonBag3", "ARTIPSBG");
	registerItem ("ArtiPork", "ARTIPORK");
	registerItem ("ArtiSpeedBoots", "ARTISPED");
	registerItem ("ArtiSuperHealth", "ARTISPHL");
	registerItem ("ArtiTeleport", "ARTIATLP");
	registerItem ("ArtiTeleportOther", "ARTITELO");
	registerItem ("PuzzBook1", "ARTIBOK1");
	registerItem ("PuzzBook2", "ARTIBOK2");
	registerItem ("PuzzCWeapon", "ARTICWEP");
	registerItem ("PuzzFlameMask", "ARTISKL2");
	registerItem ("PuzzFWeapon", "ARTIFWEP");
	registerItem ("PuzzGear1", "ARTIGEAR");
	registerItem ("PuzzGear2", "ARTIGER2");
	registerItem ("PuzzGear3", "ARTIGER3");
	registerItem ("PuzzGear4", "ARTIGER4");
	registerItem ("PuzzGemBig", "ARTIBGEM");
	registerItem ("PuzzGemBlue1", "ARTIGEMB");
	registerItem ("PuzzGemBlue2", "ARTIGMB2");
	registerItem ("PuzzGemGreen1", "ARTIGEMG");
	registerItem ("PuzzGemGreen2", "ARTIGMG2");
	registerItem ("PuzzGemRed", "ARTIGEMR");
	registerItem ("PuzzMWeapon", "ARTIMWEP");
	registerItem ("PuzzSkull", "ARTISKLL");
}


//Called from clientside functions. Activates the item with the specified index.
script "modname_useitem" (int index) net
{
	if (true)
	{
	    //Debug messages. Print item index, item name and player number.
		printbold(d:index ,s:" ", s:inventory_names[index],s:" " , d: PlayerNumber());
		log(d:index ,s:" ", s:inventory_names[index],s:" " , d: PlayerNumber());
		
		useInventory(inventory_names[index]);//THIS IS THE PART THAT DOESN'T WORK IN MP!!!
	}
}

//Initializes inventory system. Serverside.
script "modname_inventory_init" OPEN
{
	iAmServer = true;
	log(s:"this is serverside");//Debug message, shown in SP and server logs.
	itemList(); //Loads items.
}

script "modname_inventory_clientinit" ENTER CLIENTSIDE //Clients only
{
	Delay(1);
	
	//Debug message. prints 0 if it's being called from a MP client,
	//and another number in SP.
	log(s:"this is clientside: ",d:inventory_names_size); 
	
	
	if (iAmServer == 0) //Prevents all of this from happening again in SP
	{
		log(s:"loading items...");
		itemList();
		log(d:inventory_names_size);//Prints number of items.
	}
}


//Freezes player movement when using the inventory GUI, and activates it.
//Or stops the player from using it, and lets them move.
script "modname_inventory_toggle" (void) net
{
	
	if (!CheckInventory("IsUsingInventory"))
	{
		GiveInventory("IsUsingInventory",1);
		SetPlayerProperty(0, 1, PROP_TOTALLYFROZEN);
		ACS_NamedExecuteAlways("modname_inventory_show",0); //Activates GUI
	}
	
	else
	{
		TakeInventory("IsUsingInventory",1);
		SetPlayerProperty(0, 0, PROP_TOTALLYFROZEN);
	}
	
	
}



script "modname_inventory_show" (void) clientside
{
	int i,j,k,l;
	//auxiliar variables. Perhaps I should rename some of them.
	//Relevant: l is used on item indices. 
	
	int selectedX = 0; //X-coordinate of selected item.
	int selectedY = 0; //Y-coordinate of selected item.
	int useInvItem = false; //Whenever the selected item is going to be used or not.
	int buttons, newbuttons; //Key imputs.
	int buttonWaitTime; //Input cooldown.
	
	buttons = GetPlayerInput(-1, INPUT_BUTTONS); //Reads input.
	

	while(true){
		if (!CheckInventory("IsUsingInventory")) //Exit GUI.
		{
			//Erases GUI
			for (i = 40; i <= 320; i++)
			{
				HudMessage(s:""; HUDMSG_PLAIN, i, CR_UNTRANSLATED, 96.0, 96.0, 0.1);
			}
			terminate;	
		}
		
		
		
		//CONTROLS
		newbuttons = GetPlayerInput(-1, INPUT_BUTTONS);
		
		if (newbuttons != buttons || buttonWaitTime == 0 )
		{
			if (newbuttons & (BT_FORWARD|BT_LOOKUP) ) selectedY--;
			if (newbuttons & (BT_BACK|BT_LOOKDOWN) ) selectedY++;
			if (newbuttons &  (BT_LEFT|BT_MOVELEFT) ) selectedX--;
			if (newbuttons &  (BT_RIGHT|BT_MOVERIGHT) ) selectedX++;
			if (newbuttons &  (BT_USE|BT_ATTACK) ) useInvItem = true;//Use item

		}
		
		if (newbuttons != buttons) buttonWaitTime = 8;
		else if (buttonWaitTime == 0) buttonWaitTime = 1;
		else buttonWaitTime --;
		
		
		if (selectedX < 0) selectedX = SLOT_COLUMNS - 1;
		else if (selectedX >= SLOT_COLUMNS) selectedX = 0;
		
		if (selectedY < 0) selectedY = SLOT_ROWS - 1;
		else if (selectedY >= SLOT_ROWS) selectedY = 0;
		
		
		
		
		//Draw squares
		
		SetHudSize(640, 400, TRUE);
		SetFont("INVBACK");
		HudMessage(s:"A"; HUDMSG_PLAIN, 310, CR_UNTRANSLATED, 96.0, 96.0, 0.0);
		HudMessage(s:"A"; HUDMSG_PLAIN, 311, CR_UNTRANSLATED, 224.0, 96.0, 0.0);
		HudMessage(s:"A"; HUDMSG_PLAIN, 312, CR_UNTRANSLATED, 96.0, 224.0, 0.0);
		HudMessage(s:"A"; HUDMSG_PLAIN, 313, CR_UNTRANSLATED, 224.0, 224.0, 0.0);
		
		
		k = 240;
		
		
		
		for (i = 0 ; i < SLOT_COLUMNS ; i++)
		{
			for (j = 0 ; j < SLOT_ROWS ; j++)
			{
				if (i == selectedX && j == selectedY) SetFont("INVSLOTS");
				else SetFont("INVSLOT");
				HudMessage(s:"A"; HUDMSG_PLAIN, k, CR_UNTRANSLATED, i*32.0 + 48.0, j*32.0 + 48.0, 0.0);
				k++;
			}
		}
		
		
		//Render items
		k = 80;
		i = 0;
		j = 0;
		for (l = 0; l < inventory_names_size; l++)
		{
			//Render only if it's in the player's inventory
			if (checkInventory(inventory_names[l]))
			{
				
				if (i == selectedX && j == selectedY && useInvItem)//Uses the item.
				{
					useInvItem = false;
					
					//Debug message. Prints inventory item index.
					//(which should be the same as the one printed from the NET script)
					log(d:l ,s:" ",s:inventory_names[l],s:" " , d: PlayerNumber());
					
					//Calls NET script.
					NamedRequestScriptPuke("modname_useItem", l,0,0);
				}
				
				//Icon
				SetFont(inventory_icons[l]);
				HudMessage(s:"A"; HUDMSG_PLAIN, k, CR_UNTRANSLATED, i*32.0 + 48.0, j*32.0 + 48.0, 0.05);
				
				//Ammount
				SetFont("INDEXFONT");
				HudMessage(d:CheckInventory(inventory_names[l]); HUDMSG_PLAIN, k + 80 , CR_UNTRANSLATED, i*32.0 + 48.0, j*32.0 + 48.0, 0.05);
				
				i++;
				k++;
				if (i >= SLOT_COLUMNS)
				{
					i = 0;
					j++;
				}
			}
				
		}
		
		
		
		buttons = newbuttons;
		
		delay(1);
	}
}


User avatar
arkore
Forum Regular
Posts: 183
Joined: Mon Dec 17, 2012 8:01 pm

Re: Array-based UseInventory doesn't work online.

#4

Post by arkore » Fri Jan 26, 2018 7:45 pm

If you don't get any help here, try posting in zdoom.org forums, since Zandronum is forked from the ZDoom engine.

Post Reply