Jump to content

Barter script commands


Tokei

Recommended Posts


  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  658
  • Reputation:   663
  • Joined:  11/12/12
  • Last Seen:  

Heya,

These script commands are an alternative for those who do not want to use yaml for making barter shops. The shops can be reloaded by reloading the script, using the barter_clear command. The NPC location is defined just like a regular NPC and then using callshop <npc barter name>, just like regular shop types (which is already possible without this diff, but I thought I'd mention it anyway).

  • Removes all items from a barter shop
    barter_clear <npc name>;
  • Add item, not extended
    barter_add <npc name>,<item id>,<amount>,<req item id>,<req amount>;
  • Add item, extended
    barter_add_ex <npc name>,<item id>,<amount>,<zeny>{,<req item id>,<req amount>,<req refine>}*;

Here's a script example:

prontera,150,188,0	script	Barter NPC	77,{
	mes "[Barter NPC]";
	next;
	
	switch(select("Normal barter shop.:Extended barter shop.:")) {
		case 1:
			mes "[Barter NPC]";
			mes "...";
			close2;
			callshop "barter_test_npc";
			end;
		case 2:
			mes "[Barter NPC]";
			mes "...";
			close2;
			callshop "barter_test_npc_ex";
			end;
	}
	
	end;
OnInit:
	barter_clear "barter_test_npc";
	barter_add "barter_test_npc", 504, 10, 501, 20;
	barter_add "barter_test_npc", 504, 10, 502, 10;
	barter_add "barter_test_npc", "White_Potion", 10, "Yellow_Potion", 3;
	
	barter_clear "barter_test_npc_ex";
	barter_add_ex "barter_test_npc_ex", "Zeny_Knife", 5, 5000, "Knife", 1, 9;
	barter_add_ex "barter_test_npc_ex", "Zeny_Knife", 5, 5000, "Knife", 1, 9, "White_Potion", 10, 0;
	barter_add_ex "barter_test_npc_ex", "Zeny_Knife", 5, 5000, "Knife", 1, 9, "White_Potion", 10, 0, "White_Potion", 10, 0;
	end;
}

prontera,152,188,0	script	Barter NPC2	77,{
	callshop "barter_test_npc";
	end;
}

And here's the diff file:

diff --git a/src/map/npc.cpp b/src/map/npc.cpp
index d227467ed..37f50d94d 100644
--- a/src/map/npc.cpp
+++ b/src/map/npc.cpp
@@ -842,6 +842,26 @@ void BarterDatabase::loadingFinished(){
 
 BarterDatabase barter_db;
 
+struct npc_data* npc_create_dummy_barter_npc(const char *npcname) {
+	struct npc_data* nd = npc_create_npc(-1, 0, 0);
+
+	npc_parsename(nd, npcname, nullptr, nullptr, __FILE__ ":" QUOTE(__LINE__));
+
+	nd->class_ = -1;
+	nd->speed = 200;
+
+	nd->bl.type = BL_NPC;
+	nd->subtype = NPCTYPE_BARTER;
+
+	nd->u.barter.extended = false;
+
+	map_addiddb(&nd->bl);
+
+	strdb_put(npcname_db, npcname, nd);
+
+	return nd;
+}
+
 /**
  * Returns the viewdata for normal NPC classes.
  * @param class_: NPC class ID
diff --git a/src/map/npc.hpp b/src/map/npc.hpp
index 0a0c104e6..82ad2cf3d 100644
--- a/src/map/npc.hpp
+++ b/src/map/npc.hpp
@@ -1479,6 +1479,8 @@ enum e_npcv_status : uint8 {
 	NPCVIEW_INVISIBLE = 0x29,
 	NPCVIEW_CLOAK     = 0x30,
 };
+
+struct npc_data* npc_create_dummy_barter_npc(const char* npcname);
 struct view_data* npc_get_viewdata(int class_);
 int npc_chat_sub(struct block_list* bl, va_list ap);
 int npc_event_dequeue(map_session_data* sd,bool free_script_stack=true);
diff --git a/src/map/script.cpp b/src/map/script.cpp
index 5aeebe228..6742ab8c4 100644
--- a/src/map/script.cpp
+++ b/src/map/script.cpp
@@ -26916,6 +26916,154 @@ BUILDIN_FUNC(preg_match) {
 #endif
 }
 
+/*==========================================
+ * Removes all items from a barter shop
+ * barter_clear <npc name>;
+ *------------------------------------------*/
+BUILDIN_FUNC(barter_clear)
+{
+	const char* npcname = script_getstr(st, 2);
+	std::shared_ptr<s_npc_barter> barter = barter_db.find(npcname);
+	
+	if (barter != nullptr) {
+		barter->items.clear();
+	}
+
+	return SCRIPT_CMD_SUCCESS;
+}
+
+/*==========================================
+ * Add an item to the barter shop
+ * Not extended:
+ * barter_add <npc name>,<item id>,<amount>,<req item id>,<req amount>;
+ *
+ * Extended:
+ * barter_add_ex <npc name>,<item id>,<amount>,<zeny>{,<req item id>,<req amount>,<req refine>}*;
+ *------------------------------------------*/
+BUILDIN_FUNC(barter_add)
+{
+	const char* npcname = script_getstr(st, 2);
+	std::shared_ptr<s_npc_barter> barter = barter_db.find(npcname);
+	struct npc_data* nd = npc_name2id(npcname);
+	const char* command = script_getfuncname(st);
+
+	if (barter == nullptr) {
+		barter = std::make_shared<s_npc_barter>();
+		barter->name = npcname;
+		barter_db.put(npcname, barter);
+	}
+
+	if (nd == nullptr) {
+		nd = npc_create_dummy_barter_npc(npcname);
+	}
+
+	int index = barter->items.size();
+
+	std::shared_ptr<s_npc_barter_item> item = std::make_shared<s_npc_barter_item>();
+	item->index = index;
+	barter->items[index] = item;
+	
+	if (strcmpi(command, "barter_add_ex") == 0) {
+		nd->u.barter.extended = true;
+	
+		if (script_isstring(st, 3)) {
+			const char* name = script_getstr(st, 3);
+	
+			std::shared_ptr<item_data> id = item_db.searchname(name);
+	
+			if (id == nullptr) {
+				ShowError("buildin_barter_add: Nonexistant item %s\n", name);
+				return SCRIPT_CMD_FAILURE;
+			}
+	
+			item->nameid = id->nameid;
+		}
+		else {
+			item->nameid = script_getnum(st, 3);
+		}
+	
+		item->stock = script_getnum(st, 4);
+		item->stockLimited = false;
+		item->price = script_getnum(st, 5);
+	
+		int offset = 6;
+	
+		while (script_hasdata(st, offset) && script_hasdata(st, offset + 1) && script_hasdata(st, offset + 2)) {
+			std::shared_ptr<s_npc_barter_requirement> requirement = std::make_shared<s_npc_barter_requirement>();
+	
+			requirement->index = (uint16)item->requirements.size();
+	
+			if (script_isstring(st, offset)) {
+				const char* name = script_getstr(st, offset);
+	
+				std::shared_ptr<item_data> id = item_db.searchname(name);
+	
+				if (id == nullptr) {
+					ShowError("buildin_barter_add: Nonexistant item %s\n", name);
+					return SCRIPT_CMD_FAILURE;
+				}
+	
+				requirement->nameid = id->nameid;
+			}
+			else {
+				requirement->nameid = script_getnum(st, offset);
+			}
+	
+			requirement->amount = script_getnum(st, offset + 1);
+			requirement->refine = script_getnum(st, offset + 2);
+			item->requirements[requirement->index] = requirement;
+			offset += 3;
+		}
+	}
+	else {
+		nd->u.barter.extended = false;
+		
+		if (script_isstring(st, 3)) {
+			const char* name = script_getstr(st, 3);
+		
+			std::shared_ptr<item_data> id = item_db.searchname(name);
+		
+			if (id == nullptr) {
+				ShowError("buildin_barter_add: Nonexistant item %s\n", name);
+				return SCRIPT_CMD_FAILURE;
+			}
+		
+			item->nameid = id->nameid;
+		}
+		else {
+			item->nameid = script_getnum(st, 3);
+		}
+		
+		item->stock = script_getnum(st, 4);
+		item->stockLimited = false;
+	
+		std::shared_ptr<s_npc_barter_requirement> requirement = std::make_shared<s_npc_barter_requirement>();
+		
+		requirement->index = 0;
+		
+		if (script_isstring(st, 5)) {
+			const char* name = script_getstr(st, 5);
+		
+			std::shared_ptr<item_data> id = item_db.searchname(name);
+		
+			if (id == nullptr) {
+				ShowError("buildin_barter_add: Nonexistant item %s\n", name);
+				return SCRIPT_CMD_FAILURE;
+			}
+		
+			requirement->nameid = id->nameid;
+		}
+		else {
+			requirement->nameid = script_getnum(st, 5);
+		}
+		
+		requirement->amount = script_getnum(st, 6);
+		item->requirements[0] = requirement;
+	}
+
+	return SCRIPT_CMD_SUCCESS;
+}
+
 /// script command definitions
 /// for an explanation on args, see add_buildin_func
 struct script_function buildin_func[] = {
@@ -27623,6 +27771,10 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(isdead, "?"),
 	BUILDIN_DEF(macro_detector, "?"),
 
+	BUILDIN_DEF(barter_clear, "s"),
+	BUILDIN_DEF(barter_add, "svi*"),
+	BUILDIN_DEF2(barter_add, "barter_add_ex", "svii*"),
+
 #include "../custom/script_def.inc"
 
 	{NULL,NULL,NULL},

Quick notes:

  • There isn't a whole lot of error handling. Do... not use an existing NPC name for the barter name if you don't want to crash, but otherwise, should be fine!
  • There is no handling for stocks. You can add parameters to it in the script command if you feel like it, but I've personally never used this option so I just didn't add it.

barter.diff

  • Upvote 1
  • Love 2
  • MVP 3
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  67
  • Reputation:   2
  • Joined:  08/09/13
  • Last Seen:  

Thank you as always!

Link to comment
Share on other sites

  • 2 months later...

  • Group:  Members
  • Topic Count:  38
  • Topics Per Day:  0.02
  • Content Count:  206
  • Reputation:   10
  • Joined:  08/30/19
  • Last Seen:  

is this will work on 2020 Git?

Link to comment
Share on other sites

  • 8 months later...

  • Group:  Members
  • Topic Count:  27
  • Topics Per Day:  0.01
  • Content Count:  159
  • Reputation:   26
  • Joined:  11/20/11
  • Last Seen:  

no refine for item to barter ex

+9 Note Headphones = +9 Hat and +0 Note Headphones?

just asking if this is possible or not thank you :3

have a nice day everyone

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  658
  • Reputation:   663
  • Joined:  11/12/12
  • Last Seen:  

17 hours ago, Ice Bear said:

no refine for item to barter ex

+9 Note Headphones = +9 Hat and +0 Note Headphones?

just asking if this is possible or not thank you :3

have a nice day everyone

That's not possible, the client doesn't support that feature. You'd have to make a custom system for it, and it would still not display properly. A lapine box might work better? Not sure. You'll probably have to end up doing it with a boring script though, since it's hard to handle two refines otherwise.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  27
  • Topics Per Day:  0.01
  • Content Count:  159
  • Reputation:   26
  • Joined:  11/20/11
  • Last Seen:  

5 hours ago, Tokei said:

ill not display properly. A lapine box might work better? Not sure. You'll probably have to end up doing it with a boring script though, since it's hard to handle two refines otherwise.

I see i just remember a shop that sells items with refine (eAthena days) cant find it anymore x-x but thanks tokei for giving us explanations ❤️

Link to comment
Share on other sites


  • Group:  Forum Moderator
  • Topic Count:  93
  • Topics Per Day:  0.02
  • Content Count:  10013
  • Reputation:   2346
  • Joined:  10/28/11
  • Last Seen:  

@offtopic 

On 2/29/2020 at 6:45 PM, Emistry said:

as far as I know, by default shop doesn't support refined items.

the only one who I have seen manage to make this mod in the past was @Epoque back in eathena, and the link is no longer available .

or perhaps you could try ask him to update it if he ever have time or interested to do it.

it was something that look like this https://i.imgur.com/L38UPvm.png , he probably make use of the vending system to make it possible.

(dont ask me for source code, i dont have it)

 

btw would the barter script command above with together with the existing yaml version?

wouldn't it be better to make a PR have it merge into rathena too? that could help expand the way we create npc in a much interested way too

Edited by Emistry
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...