Graal Forums

Graal Forums (https://forums.graalonline.com/forums/index.php)
-   NPC Scripting (https://forums.graalonline.com/forums/forumdisplay.php?f=8)
-   -   Problem using a level NPC that's joined to a class (https://forums.graalonline.com/forums/showthread.php?t=134264114)

xXziroXx 08-06-2011 08:36 PM

Quote:

Originally Posted by fowlplay4 (Post 1662229)
transferring data from the server-side to the client-side in a level npc can be a un-needed pain in the ass

Uh, why? :noob:

fowlplay4 08-06-2011 09:17 PM

Quote:

Originally Posted by xXziroXx (Post 1662236)
Uh, why? :noob:

You'd have to rig something together using a trigger system or attributes. For the fairly new scripter that task could be overwhelming and/or adds un-needed complexity right now.

Whereas if you store it twice, once on the server-side and once on the client-side. You have access to it on the client-side right away without sending it through your server-to-client data routing system.

Then when his shop is working the way he wants, he can always go in after and setup a way to sync the shop data to the client.

Adddeeee 08-08-2011 10:12 PM

This is what we've got so far!

Although I'm interested in re-doing the shop with DB NPC's instead of putting all the item information in the shop class. Do you think that would be more efficient or is this a good solution? Don't really know how to set it all up using DB NPC's yet though.

PHP Code:

function onActionBuyItem(cmdselected)

  if(
cmd == "Buy")
  {
    for(
temp.itemthis.listofitems)
    {
      if(
temp.item[0] == selected)
      {
        if(
player.rupees temp.item[3])
        {
          
player.chat "Not enough rupees!";
        }
        else
        {
          
player.chat "Bought " temp.item[1] @ "!";
          
player.rupees player.rupees temp.item[3];
          
this.money this.money temp.item[3];
          
this.chat this.money;
          
player.addweapon(temp.item[2]);
        }
      }
    }
  }
}

function 
onCreated()
{
  
this.setShape(13232); 
  
this.listofitems = {{"Shop_Item_Fireball""Fireball""split_fireball"30}, 
                      {
"Shop_Item_Sword""Sword""split_sword"20},
                      {
"Shop_Item_Bow""Bow""split_bow"10}
                     };
}

//#CLIENTSIDE
function onPlayerTouchsMe()
{  
  new 
GuiBitmapBorderCtrl("Shop_Window"
  {
    
this.profile GuiBitmapBorderProfile;
    
this.width screenwidth 2;
    
this.height screenheight 2;
    
this.screenwidth this.width 2;
    
this.screenheight this.height 2;
    
this.canmove false;
    
this.canresize false;
    
    new 
GuiButtonCtrl("Shop_Button")
    {
      
width 100;
      
height 40;
      
Shop_Window.width this.width 2;    
      
Shop_Window.height this.height 10;
      
text "Buy";
    }
        
    new 
GuiShowImgCtrl("Shop_Item_Fireball"
    {
      
20;
      
20;
      
width 32;
      
height 32;
      
      
this.imageselected "split_fireball_selected.png";
      
this.imagenotselected "split_fireball.png";
      
this.image this.imageselected;
      
thiso.catchevent(this.name"onMouseDown""onItemSelected");
    }
    
    new 
GuiShowImgCtrl("Shop_Item_Sword"
    {
      
Shop_Item_Fireball.Shop_Item_Fireball.width 20;
      
20;
      
width 32;
      
height 32;
      
      
this.imageselected "split_sword_selected.png";
      
this.imagenotselected "split_sword.png";
      
this.image this.imagenotselected;
      
thiso.catchevent(this.name"onMouseDown""onItemSelected");
    }
    
    new 
GuiShowImgCtrl("Shop_Item_Bow"
    {
      
Shop_Item_Sword.Shop_Item_Sword.width 20;
      
20;
      
width 32;
      
height 32;
      
      
this.imageselected "split_bow_selected.png";
      
this.imagenotselected "split_bow.png";
      
this.image this.imagenotselected;
      
thiso.catchevent(this.name"onMouseDown""onItemSelected");
    }
  }
  
Shop_Window.show();
  
this.listofitems = {Shop_Item_FireballShop_Item_SwordShop_Item_Bow};
  
this.itemselected this.listofitems[0].name;
}

function 
onMouseDown()
{
  if(!((
mousescreenx in |Shop_Window.xShop_Window.Shop_Window.width|)
      &&(
mousescreeny in |Shop_Window.yShop_Window.Shop_Window.height|)))
  {
    
Shop_Window.hide();
  }
}

function 
Shop_Button.onMouseDown()
{
  
triggeraction(this.0.5this.0.5"BuyItem""Buy"this.itemselected);
  
Shop_Window.makefirstresponder(true);
}

function 
onItemSelected(selected
{
  for(
tempi 0temp.this.listofitems.size();temp.++) 
  {
    
temp.item this.listofitems[i];
    
temp.item.image = (temp.item == selected temp.item.imageselected temp.item.imagenotselected);
  }
  
  
this.itemselected selected.name;



cbk1994 08-08-2011 10:26 PM

You can use += and -= to add/subtract from a value (purely based on your preference, but most people do that).

Besides that, the only thing that sticks out is the way you're forming your array. Rather than looping through an array, use it like a hash map.

PHP Code:

function onCreated()
{
  
this.setShape(13232);
  
this.item.fireball = {"Fireball""split_fireball"30};
  
this.item.sword = {"Sword""split_sword"20};
  
this.item.bow = {"Bow""split_bow"10};


Then, to access it, you can do:

PHP Code:

temp.itemInfo this.item.(@ selected); 


Adddeeee 08-08-2011 10:34 PM

Okay, thank you very much :)

So you don't think we need to re-build it using DB NPCs?

We don't really know how to use a DB NPC properly but I understand that's the way the "pro's" are doing it?

Thank you :)

cbk1994 08-08-2011 11:21 PM

I would recommend a DB NPC only because it will let you keep one copy of the data rather than keeping it in a class joined to many NPCs. As a general rule, I would recommend not storing data in classes.

Adddeeee 08-09-2011 12:26 AM

Then we will try that solution :)

If we use a DB NPC named DB_Items we could store all the information regarding the items in that NPC.

But what happens with the clientside of the level NPC? Shall we have a copy of all the items information on the clientside? Because we can't read the DB NPCs information from the client side right?

Thank you :)

Mark Sir Link 08-09-2011 12:36 AM

Quote:

Originally Posted by Adddeeee (Post 1662565)
Then we will try that solution :)

If we use a DB NPC named DB_Items we could store all the information regarding the items in that NPC.

But what happens with the clientside of the level NPC? Shall we have a copy of all the items information on the clientside? Because we can't read the DB NPCs information from the client side right?

Thank you :)

triggerclient a weapon with the data you want to send, IE, have a class join the generic shop class, have that triggerserver the NPC when you want the shop to open, then have the NPC trigger a weapon the player has that opens the shop GUI with the information provided. Can have a trigger in the class as well to hide the shop should the player leave the level or get too far away.


PHP Code:

triggerserver("npc""DB_Items""getitems"//possibly level name as well to restrict what shops have what items

triggerclient("gui"shopweaponname"senditems"this.items); 


Adddeeee 08-09-2011 12:52 AM

Ah I see, will try this later on when I get the GUI to be more flexible :) Sorry for asking so many dumb questions, but I'm kind of stuck both on the DB NPC and on the GUI part!

Why doesn't this work:

PHP Code:

  this.listofitems = {{"Fireball""split_fireball""split_fireball.png""split_fireball_selected.png"30}, 
                      {
"Sword""split_sword""split_sword.png""split_sword_selected.png"20},
                      {
"Bow""split_bow""split_bow.png""split_bow_selected.png"10}
                     }; 
  new 
GuiShowImgCtrl(this.listofitems[0][0]) 
  {
    
20;
    
20;
    
width 32;
    
height 32;
    
    
this.imageselected this.listofitems[0][3];
    
this.imagenotselected this.listofitems[0][2];
    
this.image this.imageselected;
    
thiso.catchevent(this.name"onMouseDown""onItemSelected");
  }
  
Shop_Window.addControl(this.listofitems[0][0]);
  
Shop_Window.show(); 

when this works just fine:

PHP Code:

  this.listofitems = {{"Fireball""split_fireball""split_fireball.png""split_fireball_selected.png"30}, 
                      {
"Sword""split_sword""split_sword.png""split_sword_selected.png"20},
                      {
"Bow""split_bow""split_bow.png""split_bow_selected.png"10}
                     };

  new 
GuiShowImgCtrl(this.listofitems[0][0]) 
  {
    
20;
    
20;
    
width 32;
    
height 32;
    
    
this.imageselected "split_fireball_selected.png";
    
this.imagenotselected "split_fireball.png";
    
this.image this.imageselected;
    
thiso.catchevent(this.name"onMouseDown""onItemSelected");
  }
  
Shop_Window.addControl(this.listofitems[0][0]);
  
Shop_Window.show(); 

The only difference is that in the first code sample, I read the string from the array listofitems and in the second code sample I write the string directly.

Hmm...

Thank you :)

fowlplay4 08-09-2011 12:55 AM

'this' refers to the GuiShowImgCtrl instead of the level npc or weapon. You have to use thiso to access your listofitems.

I would recommend doing.. new GuiShowImgCtrl("Split_ShopItem_" @ this.listofitems[0][0]) instead of just using the item's name as well.

Adddeeee 08-09-2011 12:58 AM

Omg, thank you! Getting a little tired ;D

Adddeeee 08-09-2011 06:34 PM

To start with I want to thank you all for your replies and good support :) We're closing in on the main goal!

We don't have a DB just yet, but we're close to it...I think!

This is what we've got so far:

Class shop
PHP Code:

function onCreated()
{
   
setShape(13232);
}

function 
onPlayerTouchsMe()
{
  
this.listofitems = {{"Fireball""split_fireball""split_fireball.png""split_fireball_selected.png"30}, 
                        {
"Sword""split_sword""split_sword.png""split_sword_selected.png"20},
                        {
"Bow""split_bow""split_bow.png""split_bow_selected.png"10}
                       };
                     
  
triggerclient("gui""-shopcontrol"this.listofitemsthis.xthis.y);
}

function 
onActionBuyItem()
{
   
this.chat "I received your request!";


Class shop serves as our temp DB. We will fix a DB to hold the information about the items. But for now it's just a class :) This class is joined to the NPC who is the shopkeeper. When a player touchs him/her it will send a triggerclient to the shopcontrol weapon:

Weapon -shopcontrol:

PHP Code:


//#CLIENTSIDE
function onActionClientSide(listofitemsnpcxnpcy)
{
  
this.npcx npcx;
  
this.npcy npcy;
  
this.listofitems listofitems;
  
  new 
GuiBitmapBorderCtrl("Shop_Window"
  {
    
this.profile GuiBitmapBorderProfile;
    
this.width screenwidth 2;
    
this.height screenheight 2;
    
this.screenwidth this.width 2;
    
this.screenheight this.height 2;
    
this.canmove false;
    
this.canresize false;
    
    new 
GuiButtonCtrl("Shop_Button")
    {
      
width 100;
      
height 40;
      
Shop_Window.width this.width 2;    
      
Shop_Window.height this.height 10;
      
text "Buy";
    } 
  }
  
  for(
0this.listofitems.size(); i++)
  {
    new 
GuiShowImgCtrl("Shop_Item_" thiso.listofitems[i][0]) 
    {
      
20 20 32;
      
20;
      
width 32;
      
height 32;
    
      
this.imageselected thiso.listofitems[i][3];
      
this.imagenotselected thiso.listofitems[i][2];
      
this.image this.imagenotselected;
      
thiso.catchevent(this.name"onMouseDown""onItemSelected");
    }
    
Shop_Window.addControl("Shop_Item_" thiso.listofitems[i][0]);
  }
 
  
Shop_Window.show();
}

function 
onMouseDown()
{
  if(!((
mousescreenx in |Shop_Window.xShop_Window.Shop_Window.width|)
      &&(
mousescreeny in |Shop_Window.yShop_Window.Shop_Window.height|)))
  {
    
Shop_Window.destroy();
  }
}

function 
Shop_Button.onMouseDown()
{
  
triggeraction(this.npcx 0.5this.npcy 0.5"BuyItem""Buy"this.itemselected.substring("Shop_Item_".length()));
  
Shop_Window.makefirstresponder(true);
}

function 
onItemSelected(selected
{
  for(
1Shop_Window.controls.size(); ++)
  {
    
temp.control Shop_Window.controls[i];
    
temp.control.image = (temp.control == selected temp.control.imageselected temp.control.imagenotselected);
  }

  
this.itemselected selected.name;


The shopcontrol weapon is basically just a gui interface which shows all the possible items to buy.

This is where the trouble starts. When I'm about to send the chosen item back to the npc something goes wrong. It seems like the triggeraction doesn't really do what I thought it would do. I thought it would trigger the npc closest to the coordinates given in the triggeraction (x, y, ...). But maybe I'm doing it all wrong?

Also, it seems as if the NPC's shape is out of synch. The player touches it when the player is positioned at the top left tile of the NPC. Maybe there's something I've done with setshape that doesn't work?

Thank you :)

EDIT: I managed to get the data back to the NPC! So there's no problem with the triggeraction(npcx, npcy, ...) command :) But the NPC PlayerTouchsMe is still troubeling us.

EDIT2: As stated above I managed to get the triggerserver and trigger client between the NPC and the weapon to work. I have now created a DB NPC named DB_Items:

PHP Code:

function onInitialized()
{
  
onCreated();
}

function 
onCreated()
{
  
/*
    Format:
    this.item_id = {Name, WeaponName, Image, ImageWhenSelected, Price};
   */

  
this.lisofitems = {{"Fireball""split_fireball""split_fireball.png""split_fireball_selected.png"30}, 
                     {
"Sword""split_sword""split_sword.png""split_sword_selected.png"20},
                     {
"Bow""split_bow""split_bow.png""split_bow_selected.png"10}
                    };


function 
getItems()
{
  return 
this.listofitems();


Is that a proper way of scripting the DB NPC? Or do I have to trigger the DB NPC and then trigger back to the level NPC in order to get the information the DB holds?

fowlplay4 08-09-2011 07:17 PM

Here's one way of doing it, you assign a shop id to your npc.

I.e: this.shop_id = "basicshop";

PHP Code:

function onCreated() {
  
this.shop_id "basicshop";
  
this.join("shopkeeper");


DB-NPC: DB_Shops (For this example)

PHP Code:

function onCreated() {
  
// Setup Basic Shop's Item List
  
this.shop_basicshop = {
    {
"Fireball""split_fireball""split_fireball.png""split_fireball_selected.png"30}, 
    {
"Sword""split_sword""split_sword.png""split_sword_selected.png"20},
    {
"Bow""split_bow""split_bow.png""split_bow_selected.png"10}
  };
}

// Public method to retrieve the items for a specific shop
public function getShopItems(shop_id) {
  return 
this.("shop_" shop_id);


then in your NPC:

PHP Code:

// other code..

function getShopItems() {
  return 
DB_Shops.getShopItems(this.shop_id);
}

function 
onPlayerTouchsMe() {
  
// You don't need to specify "gui", you can just use the weapon's name.
  
player.triggerclient("-shopcontrol"this.shop_idgetShopItems(), this.xthis.y);


Then in your script you can just store the shop id, and display the items, and then trigger your DB-NPC, verify the purchase against the list of items for that shop, and allow the player to purchase the item.

Adddeeee 08-09-2011 07:29 PM

Thank you :) I tried something similar just now, but failed because I didn't make the function getItems in the DB NPC public. I suppose it has to be public?

fowlplay4 08-09-2011 07:37 PM

Quote:

Originally Posted by Adddeeee (Post 1662700)
Thank you :) I tried something similar just now, but failed because I didn't make the function getItems in the DB NPC public. I suppose it has to be public?

To call it from other scripts like in my class example, yes.


All times are GMT +2. The time now is 08:44 PM.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2025, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.