Jump to content
Sign in to follow this  
Graf

Выдача предмета/репутации за убийство монстров

Recommended Posts

Выдача предмета/репутации за убийство монстров

Допустим у нас есть идея:

Цитата

Выдача основной валюты(предмета). С условиями уровня и небольшого рандома.

Первоначально нам нужны цифры, с которыми мы хотим работать. Создадим массив и рейт на выпадение предмета по пути:

/resource/script/calculate/variable.lua
-- Рейт на кол-во предмета
COIN_DEMON_RAID = 1
-- Массив выпадения предмета с монстров
Monster_Coin = {}
-- С 1 по 15 уровень падает 1 предмета с шансом 20%
Monster_Coin[1] = { 1, 15, 1, 20   }
-- С 16 по 30 уровень падает 2 предмета с шансом 30%
Monster_Coin[2] = { 16, 30, 2, 30   }
-- С 31 по 45 уровень падает 3 предмета с шансом 35%
Monster_Coin[3] = { 31, 45, 2, 35   }
-- С 46 по 60 уровень падает 3 предмета с шансом 40%
Monster_Coin[4] = { 46, 60, 3, 40   }
-- С 61 по 75 уровень падает 3 предмета с шансом 45%
Monster_Coin[5] = { 61, 75, 3, 45   }

Далее мы думаем, где же использовать эти цифры.. Нужно найти функцию, которая отвечает за убийство монстров.

В данном примере я возьму:

function GetExp_PKM( dead , atk  )

Находится она в файле по пути:

/resource/script/calculate/exp_and_level.lua

И пишем в ней:

	-- Узнаем уровень монстра
	local Lv_Monster = GetChaAttr(dead, ATTR_LV)
	-- Записываем ID предмета, который будем выдавать
	local ID_Demon_Coin = 3458
	-- Создаем переменную для перебора нашего массива, который создавали в файле variable.lua
	local DataCoin
	-- Перебираем массив
	for DataCoin in Monster_Coin do
		-- Если уровень монстра >= значению в массиве и <= второму значению в массиве, то
		if Lv_Monster >= Monster_Coin[DataCoin][1] and Lv_Monster <= Monster_Coin[DataCoin][2] then
			-- Создаем рандом
			local Rand_Gives = math.random(1, 100)
			-- Проверяем день недели
			local now_week= tonumber(os.date("%w"))
            -- Если сейчас суббота или воскресенье
			if now_week == 6 or now_week == 7 then
            -- то умножаем количество выдаваемоего предмета в 2 раза                                                                                
				COIN_DEMON_RAID = COIN_DEMON_RAID * 2
			end
            -- Если наш рандом меньше. чем указан шанс в массиве..
			if Rand_Gives <= Monster_Coin[DataCoin][4] then
          		-- то выдаем предмет в количестве, указанном в массиве.
				GiveItem ( atk , 0 , ID_Demon_Coin  , Monster_Coin[DataCoin][3] * COIN_DEMON_RAID , 4 )
			end
		end
	end

 

  • Thanks 1

Share this post


Link to post
Share on other sites

Не удержался, вынесите следующую переменную из цикла for. Поставьте её до. Мелоч, но режет глаза. 😄

local now_week= tonumber(os.date("%w"))

PS: это если что сарказм. Нагрузки можно сказать и нет. Но в привычку стоит взять - объявлять такие переменные вне циклов.

UPD:
А еще, я нашел ошибку в коде. 
Из за неверного присвоения глобальной переменной, к концу выходым, дроп будет огого)

COIN_DEMON_RAID = COIN_DEMON_RAID * 2

UPD2:
Если что, в os.date(), воскресенье == 0, а не 7.

Edited by Fomin
  • Thanks 2

Share this post


Link to post
Share on other sites

Привет, @Graf!

 

Благодарю за выложенный скрипт! Не критики ради, хочется дать несколько советов, которые, по моему мнению, сделают твой скрипт еще лучше.

 

1) Для решения такой задачи удобно использовать технику хуков.  Она заключается в том, что мы сохраняем адрес оригинальной функции GetExp_PKM() в переменную GetExp_PKM__Original, создаем новую функцию с именем GetExp_PKM (т.е. перезаписываем старую функцию), реализовываем в ней необходимую нам логику и вызываем оригинальную функцию, адрес которой сохранили в переменной ранее. Таким образом, мы можем отделить новую логику от старой и уйти от редактирования оригинального кода. Также это облегчает установку и удаление подобных модификаций в будущем.

 

Например, в файле functions.lua

-- Функция вызывается когда игрок [@atk] убил монстра [@dead]
GetExp_PKM__Original = GetExp_PKM
GetExp_PKM = function(dead, atk)

	-- Вызываем оригинальную функцию
	GetExp_PKM__Original(dead, atk)
	
	-- Здесь наша логика (выдать предметы, золото и так далее)
	SystemNotice(atk, string.format("Вы победили монстра Ур.%d %s!", Lv(dead), GetChaDefaultName(dead)))

end

 

2) Как верно заметил @Fomin, глобальная переменная COIN_DEMON_RAID будет увеличиваться в четыре раза каждую неделю (в двое в субботу и в двое в воскресенье) и все это еще умножается на количество убийств монстров в выходные дни. Чтобы этого избежать, можно создать локальную копию данной переменной и работать уже с копией:

 . . .
 
local rate = COIN_DEMON_RAID 
for DataCoin in Monster_Coin do

	. . .
	
	if now_week == 6 or now_week == 7 then
		rate = rate * 2
	end
	
	. . .
	
	GiveItem ( atk , 0 , ID_Demon_Coin  , Monster_Coin[DataCoin][3] * rate , 4 )
	
	. . .

 

3) Полям таблицы Monster_Coin можно дать осознанные имена вместо численных индексов:

-- Массив выпадения предмета с монстров
Monster_Coin = {
	{lv_start = 1,  lv_end = 15, number = 1, chance = 20 },  -- С 1  по 15 уровень падает 1 предмета с шансом 20%
	{lv_start = 16, lv_end = 30, number = 2, chance = 30 },  -- С 16 по 30 уровень падает 2 предмета с шансом 30%
	{lv_start = 31, lv_end = 45, number = 2, chance = 35 },  -- С 31 по 45 уровень падает 3 предмета с шансом 35%
	{lv_start = 46, lv_end = 60, number = 3, chance = 40 },  -- С 46 по 60 уровень падает 3 предмета с шансом 40%
	{lv_start = 61, lv_end = 75, number = 3, chance = 45 },  -- С 61 по 75 уровень падает 3 предмета с шансом 45%
}

 и пример использование в коде:

if Lv_Monster >= Monster_Coin[DataCoin].lv_start and Lv_Monster <= Monster_Coin[DataCoin].lv_end then
GiveItem ( atk , 0 , ID_Demon_Coin  , Monster_Coin[DataCoin].number * COIN_DEMON_RAID , 4 )

 

Такой подход облегчит заполнение таблицы новыми данными, улучшит читаемость кода и снизит вероятность ошибок.

 

4) Цикл "for DataCoin in Monster_Coin do" можно заменить на аналогичный, но другой конструкции:

for index, item in ipairs(Monster_Coin) do
	-- Вместо Monster_Coin[DataCoin] теперь необходимо использовать item
end

Теперь вместо обращения к элементу таблицы по индексу используем конкретный элемент:

if Lv_Monster >= item.lv_start and Lv_Monster <= item.lv_end then

 

5) Согласен с @Fomin, переменные Rand_Gives и now_week можно вынести в место перед циклом.

6) Блок 

		-- Если сейчас суббота или воскресенье
		if now_week == 6 or now_week == 7 then
			-- то умножаем количество выдаваемоего предмета в 2 раза                                                                                
			COIN_DEMON_RAID = COIN_DEMON_RAID * 2
		end

можно внести в условие

if Rand_Gives <= Monster_Coin[DataCoin][4] then

 

  • Like 2

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.

Sign in to follow this  

×
×
  • Create New...