Jump to content
noanshadow

Promocode with handlechat

Recommended Posts

could guide me please how to create a system of the type promotional code of a single use, since I do not know how to implement so that it can be used only once

example

/2a1xjq for claim X item 

or

/welcome for claim welcome chest 

Share this post


Link to post
Share on other sites

You could store an array of your items for your promotions somewhere in a file with the following syntax:

— id

— quantity

— item type

— quota
— code

 

You can also modify it to allow different requirements like level and job.

 

In your chat handler, you need to load this array of items, and pseudo code for your code would look something like this:

 

for each item in your array:

    If item[‘code’] is message:

        If item[‘quota’] is -1:

            Give the items to the player

        else:

            If item[‘quota’] >= 1:

                Give items to the player

                Update item quota by item quota -= 1

                Update the file with your promo codes

            endIf

        endIf

    endIf

endForeach 


This is just an idea off the top of my head on how it can be implemented but I can already tell you that performance-wise it’s quite poorly written, so you might want to rethink on how you’re going to store the array of items and update it without using too many resources. If you’re working with the source code then perhaps it might make more sense to store that data in your database. Hope this helps!

 

  • Thanks 2

Share this post


Link to post
Share on other sites

Hello @noanshadow,

 

 

1) Create a file named 'pkodev.promo.lua' in the folder 'GameServer\resource\script\calculate\mods':

-- Print a log
print("Loading pkodev.promo.lua")

-- Check that HandleChat function exists
if (HandleChat == nil) then
	
	-- Write a log
	print("pkodev.promo.lua: Warning, the HandleChat() function is not exist!")
	
	-- Do not load the script
	return
	
end

-- Promocodes system
promo = promo or { }

-- Name of the file with promocodes
promo.file = "promocodes.dat"

-- List with promocodes
promo.list = {}

-- Save data to file
promo.save = function(path)
	
	-- Open the file
	local file, msg = io.open(path, "w")
	
	-- Check that file is open
	if (file == nil) then
		
		-- Write a log
		LG("pkodev.mod.promo", string.format("Can't save the list with promocodes to the file '%s': '%s'!", path, msg))
		return false
		
	end
	
	-- Write data
	for key, value in promo.list do
		
		-- Write a line
		local ret = file:write(string.format("{%s, %d, %d}\n", value.code, value.id, value.count))

		-- Check that line is written
		if (ret == false) then
		
			-- Write a log
			LG("pkodev.mod.promo", string.format("Can't write the data to the file '%s'!", path))
			return false
		
		end
	
	end
	
	-- Flush the data
	file:flush()
	
	-- Close the file
	file:close()
	
	-- Write a log
	LG("pkodev.mod.promo", string.format("The list with promocodes has been successfully saved to the file '%s'!", path))
	return true
	
end

-- Load data from file
promo.load = function(path)
	
	-- Remove old promocodes
	for k in pairs (promo.list) do
		promo.list[k] = nil
	end
	
	-- Open the file
	local file, msg = io.open(path, "r")
	
	-- Check that file is open
	if (file == nil) then
		
		-- Write a log
		LG("pkodev.mod.promo", string.format("Can't load the list with promocodes from the file '%s': '%s'!", path, msg))
		return false
		
	end

	-- Read file line by line
	for line in file:lines() do
			
		-- Extract data from the line
		local ret, _, code_, id_, count_ = string.find(line, "^{([A-Za-z0-9]+)%s*,%s*([0-9]+)%s*,%s*([0-9]+)}$")
		
		-- Check that string matches the pattern
		if (ret ~= nil) then
			
			-- Add data to the list
			table.insert(
				promo.list,
				{ 
					code  = code_,
					id    = id_,
					count = count_,
				}
			)
			
		end
		
	end
	
	-- Close the file
	file:close()
	
	-- Write a log
	LG("pkodev.mod.promo", string.format("%d promocodes have been succsessfully loaded from file '%s'!", table.getn(promo.list), path))
	return true

end

-- Handle chat function hook
promo.hadle_chat__original = HandleChat
HandleChat = function(role, msg)
	
	-- Check that message has the '/' symbol
	if ( string.sub(msg, 1, 1) == "/" ) then
	
		-- Get promocode
		local ret, _, code_ = string.find(msg, "^/([A-Za-z0-9]+)%s*$")
		
		-- Check that promocode is found
		if (ret ~= nil) then
			
			-- Search the promocode in the list
			for key, value in pairs(promo.list) do
				
				-- Compare promocodes
				if (value.code == code_) then
					
					-- Write a message
					BickerNotice(role, string.format("You entered the promocode '%s': %s x %d!",
						value.code, GetItemName(value.id), value.count) )
						
					
					-- Give an item
					GiveItem(role, 0, value.id, value.count, 0)
					
					-- Write a log
					LG("pkodev.mod.promo", string.format("Player '%s' entered a promocode '%s' and received '%s' x %d!",
						GetChaDefaultName(role), value.code, GetItemName(value.id), value.count) )
						
					-- Remove the promocode from the list
					promo.list[key] = nil
					
					-- Save the list to the file
					promo.save(promo.file)
					
					-- Synchronize the promocodes list
					local packet = GetPacket()
					WriteCmd(packet, 4015)
					WriteDword(packet, GetRoleID(role))
					WriteString(packet, string.format("promo.list[%d]=nil", key))
					SendPacket(role, packet)
					
					-- Do not call the original function HandleChat()
					return 0
					
				end
				
			end
			
		end
		
	end
	
	-- Call the original function HandleChat()
	return promo.hadle_chat__original(role, msg)
	
end

promo.load(promo.file)

 

2) Include it in the file 'SkillEffect.lua' after 'functions.lua':

dofile(GetResPath("script\\calculate\\mods\\pkodev.promo.lua"))

 

3) In the root directory of the GameServer create a file named 'promocodes.dat' and write the list of promocodes in the file:

{<Promocode>, <Item ID>, <Item number>}

Example:

{agjtjSfsaAS34, 1849, 45}
{kgjKKKsnggklsaa, 885, 1}
{0004121aAf, 1848, 10}

 

4) To use the promocode, you need to enter it in the local chat:

/<Promocode>

Example:

/agjtjSfsaAS34

The player will get Cake x 45.

 

5) All logs can be found in the file 'GameServer\LOG\log\pkodev.mod.promo.txt'.

 

 

  • Like 2
  • Thanks 2

Share this post


Link to post
Share on other sites

Hello @emofc,

 

You need GameServer.exe with this function. You can find it in some server files here:

 

For example [www.maindev.ru] GameServer.exe.


Share this post


Link to post
Share on other sites
On 2/10/2022 at 8:53 AM, V3ct0r said:

Hello @emofc,

 

You need GameServer.exe with this function. You can find it in some server files here:

 

For example [www.maindev.ru] GameServer.exe.

Hello vector i run it it working perfect. But the Question is : This code can be use 1 time by account like function per Mac addres? Tnh

Share this post


Link to post
Share on other sites

Hello @emofc,

 

1) In the current implementation, the promotional code is immediately deleted after use. Therefore, it makes no sense to check that the player has already used it;

2) Player can easily change their MAC address every time and use the promotional code endlessly.

 

I just realized that my script has a critical bug. On all GameServer instances, a list of promotional codes is written to their memory. When a player uses a promotional code on one GameServer.exe, the others do not know about it. Thus, the player can use the procode several times. We need to come up with a way to synchronize the list of promotional codes between several GateServer.exe. Or allow the use of promotional codes on only one map (GameServer.exe instance).


Share this post


Link to post
Share on other sites
4 hours ago, V3ct0r said:

Hello @emofc,

 

1) In the current implementation, the promotional code is immediately deleted after use. Therefore, it makes no sense to check that the player has already used it;

2) Player can easily change their MAC address every time and use the promotional code endlessly.

 

I just realized that my script has a critical bug. On all GameServer instances, a list of promotional codes is written to their memory. When a player uses a promotional code on one GameServer.exe, the others do not know about it. Thus, the player can use the procode several times. We need to come up with a way to synchronize the list of promotional codes between several GateServer.exe. Or allow the use of promotional codes on only one map (GameServer.exe instance).

Tnh for answer bro ! I hope get fix this !

Share this post


Link to post
Share on other sites

@V3ct0r i get this error:

[02-20 16:37:45]DoString HandleChat
[02-20 16:37:45]./resource/../lua/plugin/promocode.lua:42: attempt to call a table value

Line 42 starts at:

	-- Write data
	for key, value in promo.list do

 

Share this post


Link to post
Share on other sites
On 2/19/2022 at 12:10 AM, emofc said:

Tnh for answer bro ! I hope get fix this !

Fixed the bug, now it works as it should. The script has been updated.

 

On 2/20/2022 at 6:42 PM, Rinor said:

@V3ct0r i get this error:


[02-20 16:37:45]DoString HandleChat
[02-20 16:37:45]./resource/../lua/plugin/promocode.lua:42: attempt to call a table value

Line 42 starts at:


	-- Write data
	for key, value in promo.list do

 

What version of GameServer.exe are you using?


Share this post


Link to post
Share on other sites
1 hour ago, V3ct0r said:

Fixed the bug, now it works as it should. The script has been updated.

 

What version of GameServer.exe are you using?

1.38

Share this post


Link to post
Share on other sites
17 hours ago, V3ct0r said:

Fixed the bug, now it works as it should. The script has been updated.

 

What version of GameServer.exe are you using?

I’m using CO GameServer, as this was just a lua script and co gs has a working handlechat.

Share this post


Link to post
Share on other sites
On 2/23/2022 at 2:19 AM, Rinor said:

I’m using CO GameServer, as this was just a lua script and co gs has a working handlechat.

I think CO GameServer.exe uses different version of lua in which this construction is incorrect:

for key, value in promo.list do

 

You need write a new loop for your version of lua which will iterate over promo.list table.


Share this post


Link to post
Share on other sites
7 hours ago, V3ct0r said:

I think CO GameServer.exe uses different version of lua in which this construction is incorrect:


for key, value in promo.list do

 

You need write a new loop for your version of lua which will iterate over promo.list table.

The Code works fine, it even gives the Reward also the code gets deleted from the .dat files after the USE, it just for some reason throws that error at lua_err

Share this post


Link to post
Share on other sites
13 hours ago, V3ct0r said:

I think CO GameServer.exe uses different version of lua in which this construction is incorrect:


for key, value in promo.list do

 

You need write a new loop for your version of lua which will iterate over promo.list table.

Lua has two ways/iterators to iterate over tables, ipairs(table) for arrays type of tables "numeric keys", pairs(table) for key/value pairs type of tables, like "JSON" in javascript or "dictionaries" in python.

  • Thanks 1

Kind regards, AG.

Share this post


Link to post
Share on other sites

@Rinor

 

Replace line:

for key, value in promo.list do

with:

for key, value in pairs(promo.list) do

 

  • Thanks 1

Share this post


Link to post
Share on other sites
On 2/18/2022 at 5:49 PM, V3ct0r said:

Hello @emofc,

 

1) In the current implementation, the promotional code is immediately deleted after use. Therefore, it makes no sense to check that the player has already used it;

2) Player can easily change their MAC address every time and use the promotional code endlessly.

 

I just realized that my script has a critical bug. On all GameServer instances, a list of promotional codes is written to their memory. When a player uses a promotional code on one GameServer.exe, the others do not know about it. Thus, the player can use the procode several times. We need to come up with a way to synchronize the list of promotional codes between several GateServer.exe. Or allow the use of promotional codes on only one map (GameServer.exe instance).

Sorry V3ct0r but could you tell me how I can modify it so that it checks that the code has already been used because if I use the same code several times I can definitely continue using the amount of the same code that I use and add a use so that it is only active in lv 70 the code 1 you see per character when being in that lv

 

image.png.d58fa0b40241d85eb96dc8f341b87278.png

 

Share this post


Link to post
Share on other sites
On 9/4/2022 at 7:15 PM, dragontechi said:

user 3 codes ref

 

image.png.011989e91f26335ece379b25b7026f30.png

-- Print a log
print("Loading pkodev.promo.lua")

-- Check that HandleChat function exists
if (HandleChat == nil) then
	
	-- Write a log
	print("pkodev.promo.lua: Warning, the HandleChat() function is not exist!")
	
	-- Do not load the script
	return
	
end

-- Promocodes system
promo = promo or { }

-- Name of the file with promocodes
promo.file = "promocodes.dat"

-- List with promocodes
promo.list = {}

-- Save data to file
promo.save = function(path)
	
	-- Open the file
	local file, msg = io.open(path, "w")
	
	-- Check that file is open
	if (file == nil) then
		
		-- Write a log
		LG("pkodev.mod.promo", string.format("Can't save the list with promocodes to the file '%s': '%s'!", path, msg))
		return false
		
	end
	
	-- Write data
	for key, value in promo.list do
		
		-- Write a line
		local ret = file:write(string.format("{%s, %d, %d}\n", value.code, value.id, value.count))

		-- Check that line is written
		if (ret == false) then
		
			-- Write a log
			LG("pkodev.mod.promo", string.format("Can't write the data to the file '%s'!", path))
			return false
		
		end
	
	end
	
	-- Flush the data
	file:flush()
	
	-- Close the file
	file:close()
	
	-- Write a log
	LG("pkodev.mod.promo", string.format("The list with promocodes has been successfully saved to the file '%s'!", path))
	return true
	
end

-- Load data from file
promo.load = function(path)
	

	-- Open the file
	local file, msg = io.open(path, "r")
	
	-- Check that file is open
	if (file == nil) then
		
		-- Write a log
		LG("pkodev.mod.promo", string.format("Can't load the list with promocodes from the file '%s': '%s'!", path, msg))
		return false
		
	end

	-- Read file line by line
	for line in file:lines() do
			
		-- Extract data from the line
		local ret, _, code_, id_, count_ = string.find(line, "^{([A-Za-z0-9]+)%s*,%s*([0-9]+)%s*,%s*([0-9]+)}$")
		
		-- Check that string matches the pattern
		if (ret ~= nil) then
			
			-- Add data to the list
			table.insert(
				promo.list,
				{ 
					code  = code_,
					id    = id_,
					count = count_,
				}
			)
			
		end
		
	end
	
	-- Close the file
	file:close()
	
	-- Write a log
	LG("pkodev.mod.promo", string.format("%d promocodes have been succsessfully loaded from file '%s'!", table.getn(promo.list), path))
	return true

end

-- Handle chat function hook
promo.hadle_chat__original = HandleChat
HandleChat = function(role, msg)
		local ChaLv = Lv(role)
		if(ChaLv >= 70)then
	-- Check that message has the '/' symbol
	if ( string.sub(msg, 1, 1) == "/" ) then
	
		-- Get promocode
		local ret, _, code_ = string.find(msg, "^/([A-Za-z0-9]+)%s*$")
		
		-- Check that promocode is found
		if (ret ~= nil) then
			
			-- Search the promocode in the list
			for key, value in pairs(promo.list) do
				
				-- Compare promocodes
				if (value.code == code_) then
					
					-- Write a message
					BickerNotice(role, string.format("You entered the promocode '%s': %s x %d!",
						value.code, GetItemName(value.id), value.count) )
						
					
					-- Give an item
					GiveItem(role, 0, value.id, value.count, 0)
					
					-- Write a log
					LG("pkodev.mod.promo", string.format("Player '%s' entered a promocode '%s' and received '%s' x %d!",
						GetChaDefaultName(role), value.code, GetItemName(value.id), value.count) )
					

					
					-- Save the list to the file
					promo.save(promo.file)
					
					-- Do not call the original function HandleChat()
					return 0
					
				end
				
			end
			
		end
		
	end
	
	-- Call the original function HandleChat()
	return promo.hadle_chat__original(role, msg)
	
end
end

promo.load(promo.file)

edit the code now the uses of the codes are unlimited you have to be lv 70 or higher to use the code the lv can be modified but I can't find how to limit the use to only 1 use per character

Share this post


Link to post
Share on other sites
12 hours ago, dragontechi said:

Sorry V3ct0r but could you tell me how I can modify it so that it checks that the code has already been used because if I use the same code several times I can definitely continue using the amount of the same code that I use and add a use so that it is only active in lv 70 the code 1 you see per character when being in that lv

 

image.png.d58fa0b40241d85eb96dc8f341b87278.png

 

The current implementation of the script does not assume using the same promo code several times by different characters. You have to rework the system of promo codes loading, saving and storing. For example,

{promo code, item id, item amount, {a list of characters IDs who already used the promo code}}

then check that current character's ID is not in the list.


Share this post


Link to post
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.   Restore formatting

  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...