Jump to content
Angelix

Contract System

Recommended Posts

Description:
I've modified the lua scripts from @V3ct0r's Contract System Mod to be a bit more customizable. With this script you don't need to give player contracts directly via NPC since they can now be random map drops (given directly to their inventory).

 

Download:

It's hosted on GitHub to prevent loss of the script and potentially fix issues in the future if I feel like it.

 

Installation:

  • Just load the file in your server! If you have a mod/extension folder, you can go ahead and call it from there.
  • Obviously you need V3ctor's Contract System Mod.
    • This script can work on sources, but you will need to modify client source to show the item hints properly. Not hard to do, but I won't be providing anything related to that here!

Like I said, just load the file, I won't help with that, sorry! The script is a stand-alone, no other functions are needed (hopefully). The only function neeeded is already hooked.

 

Usage Details:

  • As stated on V3ctor's original thread, create a new item within your ItemInfo.
    • The item's ID must match what is defined in ContractSys.Conf.ItemID.
      • ContractSys.Conf.ItemID = XXXXX

         

    • The item's type must match ContractSys.Conf.ItemType.
      • ContractSys.Conf.ItemType = 99
    • The item's function must be the following:
      • ItemUse_ContractSys

         

  • The system must be enabled by setting ContractSys.Conf.Enabled to true.
    • ContractSys.Conf.Enabled = true

       

  • If you want contract to be given randomly by killing monsters, then this variable ContractSys.Conf.World.Enabled must be set to true.
    • ContractSys.Conf.World.Enabled = true

      In reality, this must be always set to true since there's no other option to get contracts from, they were not implemented!

  • Adjust the maximum of active contracts a player can have at a single time.
    • ContractSys.Conf.Limit

       

  • Add your map to the allowed list, set it to true and adjust the probability to your needs. The probability is from 0 to 100.
    • ContractSys.Conf.Maps['<MAP_NAME>'] = {Allow = true, Probability = 10}
    • I have some examples in there for Forsaken City, Dark Swamp and Demonic World. You can follow those as guidance.
  • Add some monsters that spawn in your map, along with their probability, minimum and maximum quantities.
    • ContractSys.Monsters['<MAP_NAME>'] = {
      	{Allow = true, ID = <MONSTER_ID>, Min = <MIN_QTY>, Max = <MAX_QTY>, Rate = <MONSTER_RATE>},
      								}
      • <MAP_NAME>: This is your map's name like "abandonedcity".
      • <MONSTER_ID>: The monster's ID that spawns in that map.
      • <MIN_QTY> / <MAX_QTY>: The minimum and maximum quantity that the player can be tasked to killed.
      • <MONSTER_RATE>: The rate as a number that is used to add weight to the item. This number will be added with the other rates from the monsters in this map's monster list, the lower the number compared to others, the lower probability this monster will appear in a contract.
    • I have some examples in there from Forsaken City, Dark Swamp and Demonic World.
  • Add some rewards to be given when completing contracts obtained from your map.
    • ContractSys.Rewards.Maps['<MAP_NAME>'] = {
      	{Allow = true, Gold = <GOLD_AMOUNT>, ID = <ITEM_ID>, Min = <MIN_QTY>, Max = <MAX_QTY>, Quality = <ITEM_QUALITY>, Rate = <REWARD_RATE>},
      	{Allow = true, Gold = <GOLD_AMOUNT>, ID = <ITEM_ID>, Min = <MIN_QTY>, Max = <MAX_QTY>, Quality = <ITEM_QUALITY>, Rate = <REWARD_RATE>},
      	{Allow = true, Gold = <GOLD_AMOUNT>, ID = <ITEM_ID>, Min = <MIN_QTY>, Max = <MAX_QTY>, Quality = <ITEM_QUALITY>, Rate = <REWARD_RATE>},
      	{Allow = true, Gold = <GOLD_AMOUNT>, ID = <ITEM_ID>, Min = <MIN_QTY>, Max = <MAX_QTY>, Quality = <ITEM_QUALITY>, Rate = <REWARD_RATE>},
      											}
      • <MAP_NAME>: Your maps' name, such as "abandonedcity".
      • <GOLD_AMOUNT>: The amount of gold to be given (if none, just set to zero).
      • <ITEM_ID>: The item's ID to be given.
      • <MIN_QTY> / <MAX_QTY>: The minimum and maximum quantity that can be given from the previous item.
      • <ITEM_QUALITY>: The quality of the item (mostly used for gems).
      • <REWARD_RATE>: The rate as a number that is used to add weight to the reward. This number will be added with the other rates from the items in this map's reward list, the lower the number compared to others, the lower probability this reward will appear in a contract.
  • Now, if you want a monster to have specific reward, you can also add that. This will override other reward tables.
    • ContractSys.Rewards.Specific[<MONSTER_ID>] = {
      	{Allow = true, Gold = <GOLD_AMOUNT>, ID = <ITEM_ID>, Min = <MIN_QTY>, Max = <MAX_QTY>, Quality = <ITEM_QUALITY>, Rate = <REWARD_RATE>},
      	{Allow = true, Gold = <GOLD_AMOUNT>, ID = <ITEM_ID>, Min = <MIN_QTY>, Max = <MAX_QTY>, Quality = <ITEM_QUALITY>, Rate = <REWARD_RATE>},
      	{Allow = true, Gold = <GOLD_AMOUNT>, ID = <ITEM_ID>, Min = <MIN_QTY>, Max = <MAX_QTY>, Quality = <ITEM_QUALITY>, Rate = <REWARD_RATE>},
      	{Allow = true, Gold = <GOLD_AMOUNT>, ID = <ITEM_ID>, Min = <MIN_QTY>, Max = <MAX_QTY>, Quality = <ITEM_QUALITY>, Rate = <REWARD_RATE>},
      								}

       

      • <MONSTER_ID>: The monster's ID that will have specific rewards.
      • <GOLD_AMOUNT>: The amount of gold to be given (if none, just set to zero).
      • <ITEM_ID>: The item's ID to be given.
      • <MIN_QTY> / <MAX_QTY>: The minimum and maximum quantity that can be given from the previous item.
      • <ITEM_QUALITY>: The quality of the item (mostly used for gems).
      • <REWARD_RATE>: The rate as a number that is used to add weight to the reward. This number will be added with the other rates from the items in this map's reward list, the lower the number compared to others, the lower probability this reward will appear in a contract.

 

Script Logic:

  1. Player defeats a monster.
  2. System will look if the map where the player is located is defined.
    1. If defined, then it will grab a monster from that list.
    2. If not defined, it will grab a monster from the generic list.
  3. It will set the monster to the contract and a random amount between the minimum and maximum quantity available.
  4. Player must defeat the quantity of the monster set within the contract.
  5. Upon completion, player must double click the contract to finish.
    1. System will look if the monster has a specific reward and choose one from there.
    2. If no specific reward is set for that monster, then it will iterate through all the maps defined to see if the monster is defined within there. If a defined monster is found, then it will grab a reward from that map's list.
    3. If no reward has been chosen, then it will grab a reward from the generic list.
  6. The gold (if any) and item (if any) will be given to player.
    1. The quantity will be random from the minimum and maximum set.
Edited by Angelix
  • Like 1

Share this post


Link to post
Share on other sites

I use your alteration on the Lua files and it works a charm. Could you suggest in what part should I do item count of the Contract ID to limit the amount of active contract each time.

 

Additional findings, in the rewards, I only able to get gem of striking and wind for the many times I enter forsaken city for now and none other drops are triggered. Is there a reason why this happening.

Edited by kyleflow
Another details

Share this post


Link to post
Share on other sites
22 hours ago, kyleflow said:

I use your alteration on the Lua files and it works a charm. Could you suggest in what part should I do item count of the Contract ID to limit the amount of active contract each time.

Didn’t think of this! So it’s not really implemented as of now. It’s not hard to do and can update it later today. 

22 hours ago, kyleflow said:

Additional findings, in the rewards, I only able to get gem of striking and wind for the many times I enter forsaken city for now and none other drops are triggered. Is there a reason why this happening.

Huh. Maybe just luck? I’ll try it out later today and check that out to see if anything is wrong with the randomness.

Edited by Angelix

Share this post


Link to post
Share on other sites

Update.

22 hours ago, kyleflow said:

I use your alteration on the Lua files and it works a charm. Could you suggest in what part should I do item count of the Contract ID to limit the amount of active contract each time.

This has been implemented now!

22 hours ago, kyleflow said:

Additional findings, in the rewards, I only able to get gem of striking and wind for the many times I enter forsaken city for now and none other drops are triggered. Is there a reason why this happening.

I just went ahead and added a new function that should handle the randomness altogether now. With this function, some of the scripts functions were modified to use that new function and all the rewards can be selected.

Just grab the file again from GitHub and you're good to go! 

 

Don't forget to modify it to your needs.

  • Like 1

Share this post


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

Update.

This has been implemented now!

I just went ahead and added a new function that should handle the randomness altogether now. With this function, some of the scripts functions were modified to use that new function and all the rewards can be selected.

Just grab the file again from GitHub and you're good to go! 

 

Don't forget to modify it to your needs.

Thank you so much !!! will load it up now.

Share this post


Link to post
Share on other sites

I know I made this worked before, but after issues with my gem, I forgot to back up the setup when I made a new server files. Do u know why I don't get reward after completing the contract. The current script for it as per below.

-----------------------------------------------------------------------------------------------------
--------------------------------------- ** Contract System ** ---------------------------------------
-----------------------------------------------------------------------------------------------------
--------------------------------- ** Author: V3ct0r @ PKOdev.NET ** ---------------------------------
------------------------------- ** Revision: Angelix @ PKOdev.NET  ** -------------------------------
-----------------------------------------------------------------------------------------------------
----- Version: 1.0 (01/12/2022) @ V3ct0r
----- * Public Version.
----- Version: 1.1 (05/11/2022) @ Angelix
----- * Change script structure.
----- * Added random world contract creation.
----- * Modified reward handler to have several different rewards.
-----------------------------------------------------------------------------------------------------

ContractSys = ContractSys or {Conf = {World = {}, Maps = {}}, Text = {}, Attr = {}, Monsters = {}, Rewards = {Maps = {}, Specific = {}}}

ContractSys.Conf.Enabled = true	--  Enable/disable the system.
ContractSys.Conf.ItemID = 07402		--  ItemID used in system.
ContractSys.Conf.ItemType = 99		--	Item's type used.
ContractSys.Conf.Limit = 1			--	Maximum amount of contracts a player can have at a single time.
ContractSys.Conf.Random = false		--	Update only one contract even if they have several contracts for the same monster? If 'true', it will be at random. If 'false', it will update all.

ContractSys.Conf.World.Enabled = true   --  Enable/disable getting random contracts from any place.

ContractSys.Conf.Maps['default'] = {Allow = false, Probability = 10}
ContractSys.Conf.Maps['garner'] = {Allow = true, Probability = 100}
ContractSys.Conf.Maps['magicsea'] = {Allow = false, Probability = 10}
ContractSys.Conf.Maps['darkblue'] = {Allow = false, Probability = 10}
ContractSys.Conf.Maps['abandonedcity'] = {Allow = false, Probability = 10}
ContractSys.Conf.Maps['darkswamp'] = {Allow = false, Probability = 10}
ContractSys.Conf.Maps['puzzleworld'] = {Allow = false, Probability = 10}

ContractSys.Conf.Maps['abandonedcity2'] = ContractSys.Conf.Maps['abandonedcity']
ContractSys.Conf.Maps['abandonedcity3'] = ContractSys.Conf.Maps['abandonedcity']
ContractSys.Conf.Maps['puzzleworld2'] = ContractSys.Conf.Maps['puzzleworld']

ContractSys.Text.Received = 'Obtained a contract to hunt %d x [%s]!'
ContractSys.Text.Remaining = 'Contract: Remaining %s to hunt: %d / %d!'
ContractSys.Text.Complete = 'Contract to hunt [%s] is complete!'
ContractSys.Text.Unfinished = 'Contract is not complete yet. Killed [%s]: (%d / %d).'
ContractSys.Text.Completed = 'You have successfully completed the contract, congratulations!'
ContractSys.Text.LimitReach = 'You cannot have more than %d contracts active at the same time!'

--  Monster Configuration.
ContractSys.Monsters.General = {
    {Allow = true, ID = 103, Min = 01, Max = 02, Rate = 001},	--	Forest Spirit
	{Allow = true, ID = 075, Min = 01, Max = 02, Rate = 001},	--	Mystic Shrub
	{Allow = true, ID = 185, Min = 01, Max = 02, Rate = 001},	--	Mystic Flower
                                }
ContractSys.Monsters['abandonedcity'] = {
	{Allow = true, ID = 720, Min = 10, Max = 15, Rate = 080},	--	Elite Wailing Warrior
	{Allow = true, ID = 721, Min = 10, Max = 15, Rate = 080},	--	Wailing Marksman
	{Allow = true, ID = 722, Min = 10, Max = 15, Rate = 080},	--	Cursed Mummy
	{Allow = true, ID = 723, Min = 10, Max = 15, Rate = 080},	--	Crazy Mummy
	{Allow = true, ID = 686, Min = 05, Max = 10, Rate = 040},	--	Sorrow Warrior
	{Allow = true, ID = 687, Min = 05, Max = 10, Rate = 040},	--	Wailing Warrior
	{Allow = true, ID = 688, Min = 05, Max = 10, Rate = 040},	--	Wailing Archer
	{Allow = true, ID = 689, Min = 05, Max = 10, Rate = 040},	--	Sorrow Archer
	{Allow = true, ID = 690, Min = 01, Max = 01, Rate = 020},	--	Sorrow Captain
	{Allow = true, ID = 691, Min = 01, Max = 01, Rate = 020},	--	Wailing Captain
	{Allow = true, ID = 692, Min = 01, Max = 01, Rate = 020},	--	Wailing Archer Captain
	{Allow = true, ID = 693, Min = 01, Max = 01, Rate = 020},	--	Sorrow Archer Captain
	{Allow = true, ID = 712, Min = 01, Max = 02, Rate = 010},	--	Abandoned Chest 1
	{Allow = true, ID = 713, Min = 01, Max = 02, Rate = 010},	--	Abandoned Chest 2
	{Allow = true, ID = 714, Min = 01, Max = 02, Rate = 010},	--	Abandoned Chest 3
	{Allow = true, ID = 673, Min = 01, Max = 01, Rate = 005},	--	Death Knight
								}
ContractSys.Monsters['darkswamp'] = {
	{Allow = true, ID = 695, Min = 10, Max = 30, Rate = 080},	--	Swamp Bog
	{Allow = true, ID = 696, Min = 10, Max = 30, Rate = 080},	--	Swamp Man
	{Allow = true, ID = 697, Min = 10, Max = 30, Rate = 080},	--	Swamp Watcher
	{Allow = true, ID = 698, Min = 10, Max = 30, Rate = 080},	--	Swamp Warden
	{Allow = true, ID = 701, Min = 10, Max = 30, Rate = 040},	--	Jungle Guardian
	{Allow = true, ID = 706, Min = 01, Max = 01, Rate = 020},	--	Master Swamp Bog
	{Allow = true, ID = 707, Min = 01, Max = 01, Rate = 020},	--	Swamp Champion
	{Allow = true, ID = 708, Min = 01, Max = 01, Rate = 020},	--	Master Swamp Watcher
	{Allow = true, ID = 709, Min = 01, Max = 02, Rate = 010},	--	Obscure Chest 1
	{Allow = true, ID = 710, Min = 01, Max = 02, Rate = 010},	--	Obscure Chest 2
	{Allow = true, ID = 711, Min = 01, Max = 02, Rate = 010},	--	Obscure Chest 3
	{Allow = true, ID = 675, Min = 01, Max = 01, Rate = 005},	--	Huge Mud Monster
								}
ContractSys.Monsters['puzzleworld'] = {
	{Allow = true, ID = 669, Min = 10, Max = 30, Rate = 080},	--	Imaginary Snow Doll
	{Allow = true, ID = 670, Min = 10, Max = 30, Rate = 080},	--	Snow Doll Spirit
	{Allow = true, ID = 671, Min = 10, Max = 30, Rate = 040},	--	Evil Snow Doll Spirit
	{Allow = true, ID = 672, Min = 10, Max = 30, Rate = 040},	--	Confused Snow Doll
	{Allow = true, ID = 725, Min = 10, Max = 30, Rate = 020},	--	Demonic Snowman
	{Allow = true, ID = 726, Min = 01, Max = 01, Rate = 020},	--	Demonic Yeti
	{Allow = true, ID = 715, Min = 01, Max = 02, Rate = 010},	--	Chest of Demonic World 1
	{Allow = true, ID = 716, Min = 01, Max = 02, Rate = 010},	--	Chest of Demonic World 2
	{Allow = true, ID = 679, Min = 01, Max = 01, Rate = 005},	--	Wandering Soul
	{Allow = true, ID = 678, Min = 01, Max = 01, Rate = 005},	--	Snowman Warlord
								}
ContractSys.Monsters['abandonedcity2'] = ContractSys.Monsters['abandonedcity']
ContractSys.Monsters['abandonedcity3'] = ContractSys.Monsters['abandonedcity']
ContractSys.Monsters['puzzleworld2'] = ContractSys.Monsters['puzzleworld']

--  When selecting a reward to handle out, it will first look if there's a monster specified in the "Specific" table.
--  If no monster is found, it will then look through the "Maps" table, if none is found, it will choose a reward from "General".
ContractSys.Rewards.General = {
	{Allow = true, Gold = 0, ID = 00860, Min = 01, Max = 01, Quality = 101, Rate = 010},	--	Gem of the Wind
	{Allow = true, Gold = 0, ID = 00861, Min = 01, Max = 01, Quality = 101, Rate = 010},	--	Gem of Striking
	{Allow = true, Gold = 0, ID = 00862, Min = 01, Max = 01, Quality = 101, Rate = 010},	--	Gem of Colossus
	{Allow = true, Gold = 0, ID = 00863, Min = 01, Max = 01, Quality = 101, Rate = 010},	--	Gem of Rage
	{Allow = true, Gold = 0, ID = 01012, Min = 01, Max = 01, Quality = 101, Rate = 010},	--	Gem of Soul
								}

ContractSys.Rewards.Maps['abandonedcity'] = {
	{Allow = true, Gold = 0, ID = 00860, Min = 01, Max = 01, Quality = 101, Rate = 010},	--	Gem of the Wind
	{Allow = true, Gold = 0, ID = 00861, Min = 01, Max = 01, Quality = 101, Rate = 010},	--	Gem of Striking
	{Allow = true, Gold = 0, ID = 00862, Min = 01, Max = 01, Quality = 101, Rate = 010},	--	Gem of Colossus
	{Allow = true, Gold = 0, ID = 00863, Min = 01, Max = 01, Quality = 101, Rate = 010},	--	Gem of Rage
	{Allow = true, Gold = 0, ID = 01012, Min = 01, Max = 01, Quality = 101, Rate = 010},	--	Gem of Soul
								}
ContractSys.Rewards.Maps['abandonedcity2'] = ContractSys.Rewards.Maps['abandonedcity']
ContractSys.Rewards.Maps['abandonedcity3'] = ContractSys.Rewards.Maps['abandonedcity']
ContractSys.Rewards.Maps['darkswamp'] = ContractSys.Rewards.Maps['abandonedcity']
ContractSys.Rewards.Maps['puzzleworld'] = ContractSys.Rewards.Maps['abandonedcity']
ContractSys.Rewards.Maps['puzzleworld2'] = ContractSys.Rewards.Maps['abandonedcity']
																
ContractSys.Rewards.Specific[0673] = {
	{Allow = true, Gold = 0, ID = 00860, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of the Wind
	{Allow = true, Gold = 0, ID = 00861, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Striking
	{Allow = true, Gold = 0, ID = 00862, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Colossus
	{Allow = true, Gold = 0, ID = 00863, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Rage
	{Allow = true, Gold = 0, ID = 01012, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Soul
	{Allow = true, Gold = 0, ID = 03422, Min = 01, Max = 01, Quality = 004, Rate = 001},	--	Chest of Forsaken City
	{Allow = true, Gold = 0, ID = 00938, Min = 01, Max = 01, Quality = 004, Rate = 001},	--	Goddess's Favor
								}
																
ContractSys.Rewards.Specific[0675] = {
	{Allow = true, Gold = 0, ID = 00860, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of the Wind
	{Allow = true, Gold = 0, ID = 00861, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Striking
	{Allow = true, Gold = 0, ID = 00862, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Colossus
	{Allow = true, Gold = 0, ID = 00863, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Rage
	{Allow = true, Gold = 0, ID = 01012, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Soul
	{Allow = true, Gold = 0, ID = 03423, Min = 01, Max = 01, Quality = 004, Rate = 001},	--	Chest of Dark Swamp
	{Allow = true, Gold = 0, ID = 00938, Min = 01, Max = 01, Quality = 004, Rate = 001},	--	Goddess's Favor
								}
																
ContractSys.Rewards.Specific[0679] = {
	{Allow = true, Gold = 0, ID = 00860, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of the Wind
	{Allow = true, Gold = 0, ID = 00861, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Striking
	{Allow = true, Gold = 0, ID = 00862, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Colossus
	{Allow = true, Gold = 0, ID = 00863, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Rage
	{Allow = true, Gold = 0, ID = 01012, Min = 01, Max = 01, Quality = 101, Rate = 001},	--	Gem of Soul
	{Allow = true, Gold = 0, ID = 03424, Min = 01, Max = 01, Quality = 004, Rate = 001},	--	Chest of Demonic World
	{Allow = true, Gold = 0, ID = 03458, Min = 01, Max = 01, Quality = 004, Rate = 001},	--	Chest of Enigma
								}
																
ContractSys.Rewards.Specific[678] = ContractSys.Rewards.Specific[679]
								
ContractSys.RewardHandler = function(Player, Item)
    local RewardList = ContractSys.Rewards.General
	Player = TurnToCha(Player)
	local TargetID  = GetItemAttr(Item, ContractSys.Attr.TargetID)
	local TargetMax = GetItemAttr(Item, ContractSys.Attr.TargetMax)
	local TargetCur = GetItemAttr(Item, ContractSys.Attr.TargetCur)
    if ContractSys.Rewards.Specific[TargetID] then
        RewardList = ContractSys.Rewards.Specific[TargetID]
    else
        for MapName, Var in pairs(ContractSys.Monsters) do
            if MapName ~= 'General' then
                for _, Monster in pairs(Var) do
                    if Monster.ID == TargetID then
                        RewardList = ContractSys.Rewards.Maps[MapName]
                    end
                end
            end
        end
    end
	local VarID, Reward = WeightedRandomnessHandler(RewardList)
	print(VarID, Reward.ID)
	if Reward.Gold ~= 0 then
		AddMoney(Player, 0, Reward.Gold)
	end
	if Reward.ID ~= 0 and GetItemName(Reward.ID) ~= 'Unknown' then
		local Quantity = math.random(Reward.Min, Reward.Max)
		GiveItem(Player, 0, Reward.ID, math.max(Quantity, 1), (Reward.Quality or 4))
	end
end

---------------------------------------
-- Constants
---------------------------------------
ContractSys.Attr.TargetID = ITEMATTR_VAL_STR
ContractSys.Attr.TargetMax = ITEMATTR_VAL_AGI
ContractSys.Attr.TargetCur = ITEMATTR_VAL_DEX

---------------------------------------
-- Hooks
---------------------------------------

ContractSys.OriginalCreat_Item = Creat_Item
Creat_Item = function(Item, ItemType, ItemLevel, ItemEvent)
	if ItemType == ContractSys.Conf.ItemType then
		Reset_item_add()
		Add_Item_Attr(ContractSys.Attr.TargetID,  0)
		Add_Item_Attr(ContractSys.Attr.TargetMax, 0)
		Add_Item_Attr(ContractSys.Attr.TargetCur, 0)
		return item_add.cnt,
			item_add.attr[1][1], item_add.attr[1][2],
			item_add.attr[2][1], item_add.attr[2][2],
			item_add.attr[3][1], item_add.attr[3][2],
			item_add.attr[4][1], item_add.attr[4][2],
			item_add.attr[5][1], item_add.attr[5][2],
			item_add.attr[6][1], item_add.attr[6][2],
			item_add.attr[7][1], item_add.attr[7][2]
	end
	return ContractSys.OriginalCreat_Item(Item, ItemType, ItemLevel, ItemEvent)
end

ContractSys.OriginalGetExp_PKM = GetExp_PKM
GetExp_PKM = function(Monster, Player)
	ContractSys.OriginalGetExp_PKM(Monster, Player)

    if not ContractSys.Conf.Enabled then
        return
    end
	Player = TurnToCha(Player)
	local MapName = GetChaMapName(Player)
	
	local ContractCount = CheckBagItem(Player, ContractSys.Conf.ItemID)
	if (ContractCount > 0) then
		local MonsterID = GetChaTypeID(Monster)
		local Contracts = {}
		local Count = 0

		for Slot = 0, (GetKbCap(Player) - 1), 1 do
			local Item = GetChaItem(Player, 2, Slot)
			if GetItemID(Item) == ContractSys.Conf.ItemID and GetItemType(Item) == 99 then
				local TargetID = GetItemAttr(Item, ContractSys.Attr.TargetID)
				if MonsterID == TargetID then
					local TargetCur = GetItemAttr(Item, ContractSys.Attr.TargetCur)
					local TargetMax = GetItemAttr(Item, ContractSys.Attr.TargetMax)
					if TargetCur < TargetMax then
						Count = Count + 1
						Contracts[Count] = {Item = Item, Cur = TargetCur, Max = TargetMax }
					end
				end
			end
		end
		if Count > 0 then
			if ContractSys.Conf.Random then
				local r = math.random(1, Count)
				Contracts[r].Cur = Contracts[r].Cur + 1
				SetItemAttr(Contracts[r].Item, ContractSys.Attr.TargetCur, Contracts[r].Cur)
				SynChaKitbag(Player, 13)
				if Contracts[r].Cur < Contracts[r].Max then
					BickerNotice(Player, string.format(ContractSys.Text.Remaining, GetMonsterName(MonsterID), Contracts[r].Cur, Contracts[r].Max))
				else
					BickerNotice(Player, string.format(ContractSys.Text.Complete, GetMonsterName(MonsterID)))
				end
			else
				for Num, Var in pairs(Contracts) do
					Var.Cur = Var.Cur + 1
					SetItemAttr(Var.Item, ContractSys.Attr.TargetCur, Var.Cur)
					SynChaKitbag(Player, 13)
					if Var.Cur < Var.Max then
						BickerNotice(Player, string.format(ContractSys.Text.Remaining, GetMonsterName(MonsterID), Var.Cur, Var.Max))
					else
						BickerNotice(Player, string.format(ContractSys.Text.Complete, GetMonsterName(MonsterID)))
					end
				end
			end
		end
	end
    if ContractSys.Conf.World.Enabled then
		if ContractCount >= ContractSys.Conf.Limit then
			SystemNotice(Player, string.format(ContractSys.Text.LimitReach, ContractSys.Conf.Limit))
			return
		end
		ContractSys.Conf.Maps[MapName] = ContractSys.Conf.Maps[MapName] or ContractSys.Conf.Maps['default']
		local Random = math.random(1, 100)
        if ContractSys.Conf.Maps[MapName].Allow and Random <= ContractSys.Conf.Maps[MapName].Probability then
            local ChosenID, Quantity = ContractSys.SelectContract(Player)
            ContractSys.CreateContract(Player, ChosenID, Quantity)
        end
    end
end
ContractSys.SelectContract = function(Player)
    local MapName = GetChaMapName(Player)
    local MonsterList = nil
    if ContractSys.Monsters[MapName] then
        MonsterList = ContractSys.Monsters[MapName]
    else
        MonsterList = ContractSys.Monsters.General
    end
	local _, Monster = WeightedRandomnessHandler(MonsterList)
	return Monster.ID, math.random(Monster.Min, Monster.Max)
end
ContractSys.CreateContract = function(Player, TargetID, Amount)
	if not ContractSys.Conf.Enabled then
		return LUA_FALSE, nil, 0
	end
	Player = TurnToCha(Player)

	if KitbagLock(Player, 0) == LUA_FALSE then
		return LUA_FALSE, nil, 0
	end
	if GetChaFreeBagGridNum(Player) == 0 then
		return LUA_FALSE, nil, 0
	end
	local r1, r2 = MakeItem(Player, ContractSys.Conf.ItemID, 1, 4)
	if r1 == 0 then
		LG("pkodev.Contract", "Can't create the Contract item (id:", ContractSys.Conf.ItemID, ")!") 
		return LUA_FALSE, nil, 0
	end

	local Item = GetChaItem(Player, 2, r2)
	local SetTargetID = SetItemAttr(Item, ContractSys.Attr.TargetID, TargetID)
	local SetTargetMax = SetItemAttr(Item, ContractSys.Attr.TargetMax, Amount)
	local SetTargetCur = SetItemAttr(Item, ContractSys.Attr.TargetCur, 0)

	if (SetTargetID == 0) or (SetTargetMax == 0) or (SetTargetCur == 0) then
		LG("pkodev.Contract", "Can't set the Contract data! TargetID = ", SetTargetID, ", Max = ", SetTargetMax, ", Cur = ", SetTargetCur)
		return LUA_FALSE, Item, r2
	end
	SynChaKitbag(Player, 13)
	SystemNotice(Player, string.format(ContractSys.Text.Received, Amount, GetMonsterName(TargetID)))
	return LUA_TRUE, Item, r2
end

ItemUse_ContractSys = function(Player, Item)
	Player = TurnToCha(Player)
	local TargetID  = GetItemAttr(Item, ContractSys.Attr.TargetID)
	local TargetMax = GetItemAttr(Item, ContractSys.Attr.TargetMax)
	local TargetCur = GetItemAttr(Item, ContractSys.Attr.TargetCur)
	if (TargetCur < TargetMax) then
		SystemNotice(Player, string.format(ContractSys.Text.Unfinished, GetMonsterName(TargetID), TargetCur, TargetMax))
		UseItemFailed(Player)
        return
	else
		SystemNotice(Player, ContractSys.Text.Completed)
		ContractSys.RewardHandler(Player, Item)
	end
end
WeightedRandomnessHandler = function(Table)
    for Num, Thing in pairs(Table) do
        if Table[Num].Allow == nil then
            Table[Num].Allow = true
        end
        Table[Num].ID = Table[Num].ID or 0
        Table[Num].Rate = Table[Num].Rate or 1
    end
	local Sum = 0
	for _, Thing in pairs(Table) do
        if Thing.Allow and Thing.Rate >= 1 then
			Sum = Sum + Thing.Rate
		end
	end
    local VarID, Choice = nil, nil
	local Index = math.random() * Sum
	for Num, Thing in pairs(Table) do
        if Thing.Allow and Thing.Rate >= 1 then
            if Index < Thing.Rate then
                VarID, Choice = Num, Thing
                break
            else
                Index = Index - Thing.Rate
            end
        end
	end
    return VarID, Choice
end

Closed* Found the issue

Edited by kyleflow
found the error.

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