Jump to content
Tokei

Barter script commands

Recommended Posts

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

  • Love 1
  • MVP 3
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...