Recipe Item System - System ghép đồ

  • Thread starter Thread starter vuongkkk
  • Ngày gửi Ngày gửi

vuongkkk

T.E.T.Я.I.S
Giới thiệu hệ thống:
- Các bạn ai cũng biết rằng rất nhiều map cần đến việc ghép đồ, nếu không muốn nói là đa số... Nhưng thực sự thì mình không ưng cái nào cả ngoài cái của Artificial.
- Nhưng system đó chỉ giúp được bạn ghép đồ 1 cách đơn giản. Nâng cao thì còn thiếu nhiều
- Cuối cùng mình đã quyết làm 1 hệ thống recipe item cho tất cả mọi người, nhất là map maker Việt và nay đã hoàn thiện.
- Ghép đồ như dota luôn !!!!!! Full hòm cũng chiến :D

How it work – Cách thức hoạt động
Để nắm được cách config cho đúng và cách dùng system bạn cần biết về cách nó hoạt động:
- Để mua đồ trong shop mặc dù hòm đồ đã đầy thì đồ đó phải là dạng đồ power up, tạm gọi nó là đồ giả. Vì vậy về căn bản 1 đồ sẽ cần làm 2 item (1 thật và 1 giả để trong shop = Powerup)
- Khi mua đồ:
+ Nếu có đủ đồ thành phần tính cả đồ vừa mua thì sẽ tiến hành ghép luôn
+ Nếu ko có đủ thì sẽ tạo 1 món đồ thật dưới chân
- Khi nhặt đồ:
+ Dù có full hòm đồ vẫn ghép được đồ dù đồ dưới đất là đồ thật, ko phải dạng powerup
+ Thực chất là đáng ra là ko có gì xảy ra được và hiện lên thông báo inventory is full
+ Nhưng do chỉnh Follow - Item range ngắn nên unit đi đến tận nơi mới có thông báo inventory
+ Nhưng do mình config thì sẽ làm mất thông báo hiện inventory full vì giờ cũng ko cần thiết có cái đó nữa. Còn nếu làm thông báo giả = SimError thì sẽ có thể bị đè lên các thông báo sẵn có của War3 trong Constant

How to config - Chỉnh để sys hoạt động chuẩn xác
- Chỉnh Gameplay Constants -> Follow range - Items = số bạn muốn
- Chỉnh RecipeTrigger -> FOLLOW_ITEM_RANGE = Follow range - Items mà bạn chỉnh bên trên
- Chỉnh Game Interface -> Sound - Inventory is full = Animation - Bolt
- Chỉnh Game Interface -> Text - Message - Inventory is full = <Space>
- Chỉnh MAX_NUM là số lượng thành phần tối đa cho 1 công thức trong map của bạn
- Item giả phải là item dạng power up thuộc class power up luôn và model là ko có gì (.mdl)
- Item thật thì class nào cũng OK nhưng đừng đặt ở class powerup
- Item charge thì đặc biệt phải để trong class charge cả item giả lẫn item thật thì mới có thể tăng charge khi ghép hoặc mua. Ko muốn để tăng charge thì đặt chỗ khác
- Item giả ko dùng để mua đồ mà chỉ để viết tooltip vào và trưng ra cùng thông báo ko cần mua item này để ghép đồ thì để trong class Artifact

How to use - Cách dùng
- Import 4 trigger: Table, RecipeItemSys, RecipeTrigger, initRecipes vào map
- Interface:
RIS_Result
Là để chứa các thông số của item sản phẩm sau khi ghép
[spoil]
PHP:
    readonly integer rawcode
    readonly integer charge
                   boolean enabled	// giúp người dùng có thể tùy chỉnh xem có thể ghép ra được món đồ này hay ko kể cả có đủ đồ thành phần
    
    static method create takes integer itemid, integer itemcharge returns RIS_Result
        // item id là raw code của item sản phẩm, charge là số lượng charge @@
[/spoil]


RIS_Recipe
Là để chứa các thông tin của các món đồ thành phần dùng để ghép
[spoil]
PHP:
    readonly RIS_Result  result  // lưu kết quả
    readonly integer count	  // lưu số item cần để ghép (ko tính charge)
    
    static method create takes RIS_Result r returns RIS_Recipe
	// result chính là để chỉ ra item cuối cùng mà công thức này tạo thành

    method add takes integer id1, integer id2, integer c returns nothing
	// id1 là rawcode item thật
	// id2 là rawcode item giả và có thể để là 0 nếu đồ đó ko có ở trong shop ko cần phải mua
	// c    là số lượng charge cần để ghép. Nếu ko phải item dạng charge thì để = 0
	// id1 và id2 luôn phải đi thành cặp. Nếu 1 id1 vốn cặp với id2 khi add mà còn có id2 khác cũng cặp với id1 thì sẽ gây lỗi hệ thống
    
    method addMulti takes integer num, integer id1, integer id2, integer c returns nothing
        // num là số lượng item (ko phải số lượng charge) cùng loại cần
        // các thông số còn lại giống như trên
        // Nếu công thức có nhiều item giống nhau để ghép thì dùng lệnh này thay vì dùng nhiều lần lệnh add

    method createComponent takes real x, real y, code c returns nothing
	// cái này dùng để tạo ra các món đồ thật trong công thức này
	// x, y là tọa độ mà các item thành phần sẽ rớt ra
	// c là function mà code trong đó sẽ dùng để thao tác với từng món đồ thành phần sau khi tạo ra
	// trong function c thì dùng bj_lastCreatedItem để thao tác với item
[/spoil]

RIS_Combiner
Là struct để tìm công thức đúng là kiểm tra có đủ item cần chưa cũng như giúp thực hiện việc ghép đồ
[spoil]
PHP:
    static method validate takes item it returns boolean
	// có tác dụng để tạo kiểm tra item it có thể dùng để ghép được hay ko
	// lệnh này buộc phải thực hiện đầu tiên!

     static method add takes item it returns nothing
    	// Thêm vào 1 item vào quá trình kiểm tra đồ thành phần
	// Không được add trùng vì sẽ làm hỏng quá trình kiểm tra

     static method addInv takes unit u returns nothing
	// Thêm tất cả đồ trong hòm của unit u vào quá trình kiểm tra
	// Không được add trùng vì sẽ làm hỏng quá trình kiểm tra

    static method create takes RIS_Result r returns RIS_Recipe
	// result chính là để chỉ ra item cuối cùng mà công thức này tạo thành
[/spoil]

RIS_RecipeItem
Là struct để đăng kí cặp item giả và thật để mua trong shop khi full hòm.
Nếu cặp item giả và thật đã có trong lúc đăng kí công thức thì ko cần phải đăng kí lại bằng cái này nữa!
[spoil]
PHP:
    static method createPair takes integer id1, integer id2 returns nothing
	// id1 = rawcode item thật
	// id2 = rawcode item giả trong shop
[/spoil]

- RecipeItemSys : chỉ mang tính là công cụ lưu giữ và xử lý thông tin ghép đồ. Không có trigger bên trong
- RecipeTrig mới là nơi xử lý các trường hợp xảy ra trong map. Đây là cái các cậu muốn custom thì vào xem. Có Comment hướng dẫn chỗ cho cách cậu edit code trong đó rồi. Thoải mái đi, miễn đúng chỗ
- initRecipe: Các cậu vào đây học hỏi cách đăng kí 1 công thức để ghép đồ nhé ;)

Advantage - Điểm mạnh
- Ko lag, số lượng công thức ghép đồ nhiều và có thể tùy chỉnh để cho hiệu quả nhất với map của bạn ;) (max = 8912 / MAX_NUM)
- 1 item có thể có nhiều công thức ghép
- Tăng charge ghép đồ với charge item và kết quả cho ra có thể là charge item luôn
- Đồ thành phẩm sau khi ghép có thể tách được (disassemble)
- Dù 1 đồ có nhiều cách ghép hay 1 cách ghép cũng có thể disassemble chuẩn

Disadvantage - Điểm yếu
- Các cậu cần phải biết cách dùng vjass hoặc jass
- Phải đọc hướng dẫn thì mới dùng được. Nếu dùng sai thì đừng đổ tại system tớ hoạt động ko chuẩn. Hãy xem lại hướng dẫn = tiếng Việt đó @@

Change Log:

Ver 2.1:
  • Thêm 1 số trường hợp có thể xảy ra khi ghép đồ mà ver trước bỏ sót
  • Thêm chức năng disassemble
  • Thêm chức năng hiển thị message khi cố mua item ko cần phải mua
  • Đã hoàn chỉnh việc ghép đồ như dota!
Ver 2.0:
  • Code giờ gọn hơn, dễ nhìn hơn, có lẽ là nhanh hơn 1 chút nữa :D

Đôi lời chia sẻ
  • Nếu anh em không cần đến chuyện ghép đồ khi hòm đồ full, thì hoàn toàn có thể dùng hệ thống ghép đồ , cái của Artificial.

Link download map demo
RIS - Recipe Item System 2.1 demo map
 
Chỉnh sửa cuối:
Ôi = Jass àk, thế thì chịu @@. Pro nào vào nhận xét và sửa lỗi giúp bạn ấy đi nào. Để mình down map demo về test thử
 
Sao bạn ko viết = Tiếng Việt hết đi :| ... Trên Việt dưới ANh mình thấy nó hơi kỳ kỳ @@
 
Àk cái system bạn do máy mình gà hay do System nhỉ? Mà zo lag lắm @@ đi dựt dựt ??
 
Sao bạn ko viết = Tiếng Việt hết đi :| ... Trên Việt dưới ANh mình thấy nó hơi kỳ kỳ @@

Cái này thì là do jass code lam = tieng A bạn ạ. Nếu bạn có jass tiếng V nhất định mình sẽ viết. Nhiều lúc đặt tên tiếng A thấy khó khó :D
Còn tiếng Việt là mình GUI cho các bạn mà. Chả lẽ lại tiếng Anh nữa thì sao dùng system mình đc. Còn cách dùng mình đã thức cả đêm để viết. Hi vọng các bạn dùng đc.

Quên mất mấy cái là
- cần jass NewGenPack để lưu system vào map. (chính xác là cần jasshelper 0.A.2.B)
- Raw code thì ctrl+D để thấy raw code của Item.
- Và dùng cho warcaft 3 bản 1.24+
 
Cái này thì là do jass code lam = tieng A bạn ạ. Nếu bạn có jass tiếng V nhất định mình sẽ viết. Nhiều lúc đặt tên tiếng A thấy khó khó :D
Còn tiếng Việt là mình GUI cho các bạn mà. Chả lẽ lại tiếng Anh nữa thì sao dùng system mình đc. Còn cách dùng mình đã thức cả đêm để viết. Hi vọng các bạn dùng đc.

Quên mất mấy cái là
- cần jass NewGenPack để lưu system vào map. (chính xác là cần jasshelper 0.A.2.B)
- Raw code thì ctrl+D để thấy raw code của Item.
- Và dùng cho warcaft 3 bản 1.24+

K . Ý mình nói là đoạn này
PHP:
//*   If you use HandleTable instead of Table, it is the same
//* but it uses handles as keys, the same with StringTable.
//*
//*  You can use Table on structs' onInit  if the struct is
//* placed in a library that requires Table or outside a library.
//*
//*  You can also do 2D array syntax if you want to touch
//* mission keys directly, however, since this is shared space
//* you may want to prefix your mission keys accordingly:
---------------------------
EDIT : SR NHầm :D ... KO đọc kỹ
 
Note hộ ông Vương 1 cái nữa là system của ông ẻm có sử dụng Hàm SetItemUserData() và GetItemUserData(). Ai có dùng system này thì nên chú ý để tránh gây xung đột
 
Nếu ai có xung đột thiệt thì bảo mình để chuyển từ ItemUserData thành Table luôn cho tiện. Cũng không khó lắm vì mình lười với cả nghĩ là dùng kiểu đó nhanh hơn kiểu dùng Table
 
Hiện nay mình đang bí đoạn làm sao để có thể bắt được event khi 1 unit chuyển đồ cho unit khác. Help me, please !!! . Hiện dù full hòm đồ miến là đã nằm dưới đất vẫn ghép được đồ. Còn chưa bắt được event khi chuyển đồ từ unit này sang unit kia nên chưa hoàn thiện đc ghép đồ như dota
 
0.0s timer sau khi "losses an item", kiểm tra (Boolean) "Item - Item Is Owned", là True thì item đang ở trong inventory của unit nào đó
 
Yeah, mình làm được hệ thống mua đồ + combine giống dota với system của bạn rồi :x
Anw, để đạt hiệu quả cao thì nên vào Game Interfere thay đổi đoạn "Inventory is full" thành " ", sau đó xài SimError để tạo thông báo Inventory Is Full để tránh dòng ý khi nhặt đồ dưới đất khi full đồ (khi combine được) ^^
 
Ừm, thế bạn làm lại hay dùng system mình vậy. Bạn đã làm được cái mua đồ trong shop khi full hòm chưa? và tích hợp nó luôn với system ghép đồ chưa ? Rồi thì mình không làm nữa, dùng của bạn luôn. Dạo này mình bận chút nên đợi 1 tuần nữa. Mình sẽ cải tiến system này để nó nhanh hơn, code gọn hơn và tích hợp luôn simError vào nữa nếu bạn chưa làm.
 
Đây là System của bạn sau khi tích hợp SimError:
Mã:
//======================================================================================
//
//                 ItemRecipeSys
//             ------------------
//
//      Version: 1.2
//      Author:  vuongkkk
//
//
//      Dung ItemRecipeSys nhu the nao?
//      """""""""""""""""""""""""""""""
//
//  ++ Them cong thuc (recipes) de ghep do
//  ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
//      + Chuan bi
//       - Tao moi 1 trigger va dat ten la "initRecipes"
//       - Them Event - Map initialization
//       - Chuyen sang dang text
//       - Them vao function Trig_iniRecipes_Actions doan code 
//          de chuan bi bien cho viec khoi tao:
//
//              local recipe r
//              local grpRecipe grp
//
//      + Tao moi 1 group of Recipes chinh la tao moi 1 tap hop cac cong thuc
//          ghep do de tao ra cung 1 loai do
//
//              set grp = NewGrpRecipe('ciri',0)
//
//          'ciri'  la raw code cua item se thu duoc sau khi ghep do
//          0       la charge cua item sau khi ghep
//          Neu la item dang charge thi can nhap 1 so luong ban muon o day
//          Khong thi se de la 0 nhu dong code vi du o tren
//      + Tao moi 1 cong thuc ghep do nhung chua co item nguyen lieu
//
//              set r = recipe.create()
//
//      + Them vao cong thuc 1 item nguyen lieu
//       - Neu item la 1 charge item thi ta dung dong lenh
//
//              call Add2Recipe('hlst',1,r)
//
//          'hlst'  la raw code cua item se dung lam nguyen lieu de ghep do
//          1       la charge cua item nguyen lieu khi ghep
//          r       la cong thuc ma ta da tao ra truoc do
//                  giup xac dinh item nguyen lieu nay la cua cong thuc nao
//       - Neu item la 1 item dang thuong thi dong lenh giong nhu tren 
//          nhung tham so dau vao thu 2 se de la 0 nhu cau lenh duoi day
//
//              call Add2Recipe('hlst',0,r)
//
//       - Neu item la 1 item dang thuong nhung can nhieu hon 1 item loai do
//          thi dong lenh la
//
//              call Add2RecipeWithNum('belv',3,r)
//
//          'belv'  la raw code cua item se dung lam nguyen lieu de ghep do
//          3       la so luong cua item nguyen lieu can khi ghep
//          r       la cong thuc ma ta da tao ra truoc do
//                  giup xac dinh item nguyen lieu nay la cua cong thuc nao
//  * Note (Chu y):
//      Neu item la 1 item dang thuong nhung can nhieu hon 1 item loai do
//      thi nen dung nhu truong hop thu 3 noi tren thay vi nhieu dong lenh
//      nhu dong lenh o truong hop 2. No se sai di cong thuc ghep do
//      Ma dung nhu truong hop 3 se do mat cong viet (hoac copy) cua ban
//      
//      + Hoan tat 1 cong thuc ghep do voi dong lenh 
//
//              call grp.addRecipe(integer(r))
//
//  * Note (Chu y):
//      Ban hoan toan co the ghep 1 do = nhieu cong thuc khac nhau
//      Moi cong thuc co thanh phan khac nhau hoac 1 so thanh phan giong nhau
//      Neu 2 cong thuc nhau hoan toan ma ban van them vao nhom cong thuc cho
//      ra loai item do thi loi la chac chan (hoan toan sai lech so voi binh
//      thuong => co van de ...). Vay doan code vi du se nhu sau:
//
//              set grp = NewGrpRecipe('belv',0)
//              set r = recipe.create()
//              call Add2RecipeWithNum('rag1',2,r)
//              call grp.addRecipe(integer(r))
//              set r = recipe.create()
//              call Add2Recipe('rde1',0,r)
//              call Add2Recipe('rag1',0,r)
//              call grp.addRecipe(integer(r))
//
//      Y nghia doan code tren (theo dong):
//
//          Tao moi 1 nhom cac cong thuc cho ra ket qua "Boots of Quel'Thalas +6"
//          Tao moi 1 cong thuc
//          Them vao cong thuc vua moi tao 2 nguyen lieu thuoc cung loai "Slippers of Agility +3"
//          Dua cong thuc vao nhom cong thuc cho ra ket qua "Boots of Quel'Thalas +6"
//          Tao moi 1 cong thuc
//          Them vao cong thuc vua tao nguyen lieu "Ring of Protection +2", so luong: 1
//          Them vao cong thuc vua tao nguyen lieu "Slippers of Agility +3", so luong: 1
//          Dua cong thuc vao nhom cong thuc cho ra ket qua "Boots of Quel'Thalas +6"
//      Vay ta da co 2 cach ghep de ra do "Boots of Quel'Thalas +6"
//      neu ban da thuc hien buoc chuan bi =]]
//
//  ++ Lay lai do nguyen lieu vua dung de ghep, xoa do da ghep duoc di
//  ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
//
//              call DisassembleItem (i, u)
//
//          i   La item ket qua tu viec ghep do ma ra
//          u   La unit se nhan lai nguyen lieu
//          Neu dung la 
//
//              call DisassembleItem (i, null)
//
//          ko co unit nao nhan lai nguyen lieu, nguyen lieu roi ngay tai
//          vi tri cua item ma ta vua pha ra de lay lai nguyen lieu
//
//  ++ Cho phep hay khong cho phep ghep de tao ra loai item nay nua 
//  ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
//
//              EnableRecipeByResult takes integer resultID, boolean flag
//
//          resultID    loai do ta vo hieu hoa hoac kich hoat lai tac dung de ghep ra no
//          flag        true neu muon kich hoat , false neu muon vo hieu hoa
//
//                  Them vao 1 map ItemRecipeSys ra sao ?
//                  """"""""""""""""""""""""""""""""""""
//
//      3 buoc :
//          - Them 3 thu vien gom Table, TriggerUtils, ItemRecipeSys.
//          - Tao moi cac cong thuc nhu huong dan tren.
//          - Chinh FOLLOW_ITEM_RANGE, PICK_ITEM_RANGE va 2 gia tri
//              co y nghia tuong duong trong "Game Constants..."
//
//
//                  Hon gi so voi cac thu vien ve ghep do khac ?
//                  """"""""""""""""""""""""""""""""""""""""""""
//
//          - Ghep do duoc ca khi hom do full (chi khi da co item duoi dat =.=!)
//          - So luong toi da cac cong thuc len den: 8190 / 6 = 1365
//          - Ho tro ghep do tu` item dang charge cung nhu tao ra item dang charge
//
//
//================================================================================================
library ItemRecipeSys initializer Init requires Table, TriggerUtils
    globals
    // This constant must be equal with game constant in map
        constant real       FOLLOW_ITEM_RANGE = 50
        constant real       PICK_ITEM_RANGE = 150
        private string      SFX_PATH = "Abilities\\Spells\\Items\\TomeOfRetraining\\TomeOfRetrainingCaster.mdl"

// ---------------  Dung thay doi phia ben duoi --------------------------------------
// x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x
// x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x
    // system variables
        private  hashtable      IRI
        private  hashtable      recipes
        private  Table          grpResult
        constant integer        MAX_INGRE_EACH_RECIPE = 6
        constant integer        iterate = MAX_INGRE_EACH_RECIPE+1
        private  integer array  recipeGetGrp
    endglobals
    
    
    //- 3 ham duoi day giup thao tac voi du lieu lien quan viec xac dinh item thuoc recipe nao
    private function IRIAddRecipe takes integer itemID, integer recipeID returns nothing
        local integer numRecipe
        if HaveSavedInteger(IRI, itemID,0) then
            set numRecipe = LoadInteger(IRI, itemID,0)
            set numRecipe = numRecipe + 1
        else
            set numRecipe = 1
        endif
            call SaveInteger(IRI, itemID,0,numRecipe)
            call SaveInteger(IRI, itemID, numRecipe, recipeID)
    endfunction
    
    private function IRICountRecipe takes integer itemID returns integer
        return LoadInteger(IRI, itemID,0)
    endfunction
    
    private function IRIGetRecipe takes integer itemID,integer no returns integer
        return LoadInteger(IRI, itemID,no)
    endfunction

    // Kiem tra hom do full hay ko
    function InventoryIsFull takes unit whichUnit returns boolean
        local integer index = 0
        local integer count = 0
        local integer size = UnitInventorySize(whichUnit)
        loop
            if not(UnitItemInSlot(whichUnit, index) == null) then
                set count = count + 1
            endif

            set index = index + 1
            exitwhen index == size
        endloop
        if count == size then
            return true
        endif
        return false
    endfunction
    
    // la doi tuong chua thong tin cu the cua 1 cong thuc
    struct recipe
        private integer array items[MAX_INGRE_EACH_RECIPE]
        private integer array charges[MAX_INGRE_EACH_RECIPE]
        private integer       count     = 0
                boolean       enable    = true
        
        method addItem2Recipe takes integer itm, integer charge returns nothing
            set .items[count] = itm
            set .charges[count] = charge
            set .count = .count + 1
        endmethod
        
        method operator [] takes integer i returns integer
            return items[i]
        endmethod
        
        method operator countItems takes nothing returns integer
            return .count
        endmethod
        
        method chargeOf takes integer i returns integer
            return charges[i]
        endmethod
        
        method operator result takes nothing returns integer
            return grpRecipe(recipeGetGrp[integer(this)]).result
        endmethod
        
        method operator chargeResult takes nothing returns integer
            return grpRecipe(recipeGetGrp[integer(this)]).chargeResult
        endmethod
        
    endstruct

    // la 1 doi tuong giup thao tac cac thong tin lien quan den nhom' cac cong thuc
    struct grpRecipe
                integer count  = 0
                integer result = 0
                integer chargeResult = 0
        
        // them 1 cong thuc vao nhom
        method addRecipe takes integer id returns nothing
            local recipe r = recipe(id)
            call SaveInteger(recipes, integer(this), .count, id)
            set recipeGetGrp[id] = integer(this)
            set .count = .count + 1
        endmethod
        
        // lay ra cong thuc theo so thu tu trong nhom
        method operator [] takes integer i returns integer
            return LoadInteger(recipes, integer(this), i)
        endmethod
        
        // enable hoac disable toan bo cac cong thuc thuoc nhom nay
        method enable takes boolean flag returns nothing
            local integer i = 0
            local recipe  r
            loop
                set r = recipe(this[i])
                set r.enable = flag
                set i = i + 1
                exitwhen i == .count
            endloop
        endmethod
    endstruct
    
    // La 1 doi tuong giup thuc hien viec ghep do
    private struct combiner
        private item    array items[iterate]
        private item    array uItems[iterate]
        private integer array itemIDs[iterate]
        private recipe        r
        private integer       haveNumI = 0
        
        // kiem tra item dang charge thi` don vao tang chi so charge
        method findChargeItem takes item i, unit u returns nothing
            local integer count = GetItemCharges(i)
            local integer j
            local item enumI
            if count > 0 then 
                set j = 0
                loop
                    set enumI = UnitItemInSlot(u,j)
                    if not(enumI == null) and not(enumI == i) then
                        if GetItemTypeId(enumI) == GetItemTypeId(i) then
                            set count = count + GetItemCharges(enumI)
                            call SetItemCharges(enumI, count)
                            call RemoveItem(i)
                            return
                        endif
                    endif
                    set j = j + 1
                    exitwhen j == 6
                endloop
            endif
        endmethod
        
        // Kiem tra lan luot cong thuc co loai "item i" tham gia trong hom do cua "unit u"
        // Tra ve ID cua cong thuc tim dc, tra ve 0 neu ko tim duoc
        method findRecipe takes item i, unit u returns recipe
            local integer id = GetItemTypeId(i)
            local item enumI
            local integer recipeId
            local integer j
            local integer k
            local integer count
            set count = IRICountRecipe(id)
            call .findChargeItem(i,u)
            if count == 0 then
                return 0
            endif
            set j = 0
            set k = 0
            loop
                set enumI = UnitItemInSlot(u,j)
                if not(enumI == null) and not(enumI == i) then
                    set .items[k] = enumI
                    set k = k + 1
                endif
                set j = j + 1
                exitwhen j == 6
            endloop
            if i != null then
            set .items[k] = i
            set k = k + 1
            endif
            set enumI=null
            set .haveNumI=k
            set k = 1
            loop
                set recipeId = IRIGetRecipe(id,k)
                if .checkCompos(recipeId) then
                    return .r
                endif
                set k = k + 1
                exitwhen k > count
            endloop
            return 0
        endmethod
        
        // Kiem tra co du cac thanh phan cua cong thuc co id la "recipeID"
        // Tra ve true neu dung cong thuc, false neu sai
        method checkCompos takes integer recipeID returns boolean
            local integer i = 0
            local integer j=0
            local boolean flag = true
            local recipe r = recipe(recipeID)
            
            if .haveNumI < r.countItems or r.enable == false then
                return false
            endif
            loop
                set .itemIDs[j] = GetItemTypeId(.items[j])
                set j = j+1
                exitwhen j == .haveNumI
            endloop
            loop
                set j = 0
                loop
                    if not(.itemIDs[j]==0) then
                        if r[i] == .itemIDs[j] then
                            if r.chargeOf(i) <= GetItemCharges(.items[j]) then
                                set .uItems[i] = .items[j]
                                set .itemIDs[j]=0
                                set flag = true
                                exitwhen true
                            endif
                        endif
                    endif
                    
                    set flag = false
                    set j = j + 1
                    exitwhen j == .haveNumI
                endloop
                if flag == false then
                    return false
                endif
                set i = i + 1
                exitwhen i == r.countItems
            endloop
            set .r = r
            return true
        endmethod
        
        // xoa bo cac item nguyen lieu su dung de ghep do
        method removeUsedItems takes nothing returns nothing
            local integer i = 0
            local recipe  r = .r
            local integer c = 0
            loop
                if integer(r) != 0 then
                    set c = GetItemCharges(.uItems[i])
                    if c == r.chargeOf(i) then
                        call RemoveItem(.uItems[i])
                    else
                        call SetItemCharges(.uItems[i],c - r.chargeOf(i))
                    endif
                endif
                set i = i + 1
                exitwhen i==r.countItems
                set .r = 0
            endloop
        endmethod
    endstruct
    
    function NewGrpRecipe takes integer result, integer charge returns grpRecipe
        local integer j = grpResult[result]
        local grpRecipe grp
        if j == 0 then
            set grp = grpRecipe.create()
            set grp.result = result
            set grp.chargeResult = charge
            set grpResult[result] = integer(grp)
        else
            set grp = grpRecipe(j)
        endif
        return grp
    endfunction
    
    function Add2Recipe takes integer typeI, integer charge, recipe r returns nothing
        call r.addItem2Recipe(typeI, charge)
        call IRIAddRecipe(typeI,integer(r))
    endfunction
    
    function Add2RecipeWithNum takes integer typeI, integer num, recipe r returns nothing
        local integer i = 0
        loop
            call r.addItem2Recipe(typeI, 0)
            set i = i + 1
            exitwhen i == num
        endloop
        call IRIAddRecipe(typeI,integer(r))
    endfunction
    
    function EnableRecipe takes integer recipeID, boolean flag returns nothing
        local recipe r = recipe(recipeID)
        if recipeID > 0 then
            set r.enable = flag
        endif
    endfunction
    
    function EnableRecipeByResult takes integer resultID, boolean flag returns nothing
        local grpRecipe grp = grpRecipe(grpResult[resultID])
            
        if integer(grp) > 0 then
            call grp.enable(flag)
        endif
    endfunction
    
    function DisassembleItem takes item i, unit u returns nothing
        local real x = GetItemX(i)
        local real y = GetItemY(i)
        local integer j = 0
        local recipe r
        local boolean b = IsTriggerEnabled(GetTriggeringTrigger())
        local item createdI
        
        if GetItemUserData(i) == 0 then
            return
        endif
        
        set r = recipe(GetItemUserData(i))
        if b then
            call DisableTrigger(GetTriggeringTrigger())
        endif
        call RemoveItem(i)        
        if b then
            call EnableTrigger(GetTriggeringTrigger())
        endif
        if u == null then
            loop
                set createdI = CreateItem(r[j],x,y)
                if r.chargeOf(j) > 0 then
                    call SetItemCharges(createdI, r.chargeOf(j))
                endif
                set j = j + 1
                exitwhen j == r.countItems
            endloop
        else
            set r.enable = false
            loop
                set createdI = UnitAddItemById(u,r[j])
                if r.chargeOf(j) > 0 then
                    call SetItemCharges(createdI, r.chargeOf(j))
                endif
                set j = j + 1
                exitwhen j == r.countItems
            endloop
            set r.enable = true
        endif
        set createdI = null
    endfunction    
    
    // la ham kiem tra va thuc hien viec ghep do cho unit u voi item de bat dau kiem tra
    public function Check takes unit u, item i returns boolean
        local combiner comb = combiner.create()
        local recipe found
        local integer charge
            set found = comb.findRecipe(i,u)
            if integer(found) == 0 then  
                return false
            endif
            call comb.removeUsedItems()
            set charge = found.chargeResult
            set i = CreateItem(found.result,GetUnitX(u),GetUnitY(u))
            if charge > 0 then
                call SetItemCharges(i, charge)
            endif
            call UnitAddItem(u, i)
            call SetItemUserData(i,integer(found))
            call DestroyEffect(AddSpecialEffectTarget(SFX_PATH,u,"origin"))
            call comb.destroy()
            set i = null
            set found = 0
            return true
    endfunction
    
    private function Enter_Actions takes nothing returns nothing
        local RegionTrig rTrig = RegionTrig.get(GetTriggeringTrigger())
        if GetEnteringUnit() == rTrig.spxU then            
            if Check(rTrig.spxU,rTrig.targetI) == false and InventoryIsFull(rTrig.spxU) then
                call SimError(GetOwningPlayer(rTrig.spxU),"Inventory is full!")
            endif
            call rTrig.removeLeak()
            call rTrig.destroyChain()
        endif
    endfunction
    
    private function IssuePointOrder_Actions takes nothing returns nothing
        local MTrigger trig = MTrigger.get(GetTriggeringTrigger())
        local RegionTrig rTrig = trig.parent
            call rTrig.removeLeak()
            call trig.destroyChain()
    endfunction
    
    private function Trig_1_Actions takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local item i = GetManipulatedItem()
        call Check(u,i)        
        set u = null
        set i = null
    endfunction
    
    private function Trig_2_Actions takes nothing returns nothing
    local item i = GetOrderTargetItem()
    local unit u = GetTriggerUnit()
    local integer count = 0
    local MTrigger trig
    local RegionTrig rTrig
    
        if i == null then
            return
        endif
        if InventoryIsFull(u) then
            set rTrig = RegionTrig.create()
            call rTrig.newRegionByItem(i, PICK_ITEM_RANGE * 2,PICK_ITEM_RANGE * 2)
            if RectContainsCoords(rTrig.rt, GetUnitX(u), GetUnitY(u)) then
            if Check(u,i) == false then
                call SimError(GetOwningPlayer(u),"Inventory is full!")
            endif
                call rTrig.removeLeak()
                call rTrig.destroy()
            else
                call rTrig.removeLeak()
                call rTrig.newRegionByItem(i, FOLLOW_ITEM_RANGE * 2,FOLLOW_ITEM_RANGE * 2)
                call rTrig.regis(true)
                set rTrig.spxU = u
                call TriggerAddAction(rTrig.t, function Enter_Actions)
                set trig = MTrigger.create()
                call TriggerRegisterUnitEvent( trig.t, u, EVENT_UNIT_ISSUED_POINT_ORDER )
                call TriggerAddAction(trig.t, function IssuePointOrder_Actions)
                call rTrig.addChild(trig)
            endif
        endif
        set i = null
        set u = null
    endfunction    
    
    private function Init takes nothing returns nothing
    local integer index = 0
    local trigger t = CreateTrigger()
        loop
            if GetLocalPlayer() == Player(index) then
                call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_PICKUP_ITEM, null)
            endif
            set index = index + 1
            exitwhen index == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddAction(t, function Trig_1_Actions)
        set index = 0
        set t = CreateTrigger()
        loop
            if GetLocalPlayer() == Player(index) then
                call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null)
            endif
            set index = index + 1
            exitwhen index == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddAction(t, function Trig_2_Actions)
        set IRI = InitHashtable()
        set grpResult = Table.create()
        set recipes = InitHashtable()
    endfunction
endlibrary
Đây là System mua đồ tự hợp (PowerUp ^^):
Mã:
/*
Cach xai`:
Moi khi tao. 1 Item (Permanent gi gi do), thi tao them 1 Item base tu` 1 Item PowerUp (nhu sach mau' chang han)
Sau do ghi lai RAW code cua 2 item do, goi item PowerUp la Tome, item chinh' (permanent j j do y) la Item (of course)
Tai. Map Initializing, ghi dong` code:
call AddItemTable(Tome_ID,Item_ID)
Voi Tome_ID la RAW code cua Tome, Item_ID la RAW code cua Item
Khi tao. shop, cho Shop ban Tome chu khong ban Item chinh.
*/
library InitPowerUp initializer Init requires Table, ItemRecipeSys
    globals
        public Table ItemTable
    endglobals
    
    public function AddItemTable takes integer tomeid, integer itemid returns nothing
        set ItemTable[tomeid] = itemid
    endfunction
    
    private function GiveAction takes nothing returns nothing
        local unit a = GetBuyingUnit()   
        local item b
        local location loc = GetUnitLoc(a)
        set b = CreateItemLoc(ItemTable[GetItemTypeId(GetSoldItem())],loc)
        if InventoryIsFull(a) then
            call ItemRecipeSys_Check(a,b)
        else
            call UnitAddItem(a,b)
        endif
        set a = null
        set b = null
        call RemoveLocation(loc)
        set loc = null
    endfunction
    
    private function Init takes nothing returns nothing
        local trigger a = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( a, EVENT_PLAYER_UNIT_SELL_ITEM )
        call TriggerAddAction( a, function GiveAction )
        set a = null
        set ItemTable = Table.create()
        call ItemTable.reset()
    endfunction
endlibrary
 
Sau 1 đêm chật vật với những lỗi khá vớ vẩn. Mình xìn giới thiệu RIS ver 1.3 đã có khá nhiều thay đổi. Tất cả đã được cập nhật ở đầu trang. Cám ơn những ai đã ủng hộ mình với hệ thống này. Chả biết được bao người nữa :p
Nhân tiện đây: nếu [Yami] vẫn còn sử dụng hệ thống này thì nên update bản mới vì với cách dùng của cậu thì nặng phần xử lý hơn vẻ mới này đấy. Còn nếu cậu vẫn cần cái mua đồ power up trong shop thì để mình tích hợp sau cho cậu nhé. Thực ra cũng đơn giản thôi nhưng mình buồn ngủ rồi :p

---------- Post added at 03:16 ---------- Previous post was at 02:38 ----------

Ông nào nhanh tay quá, mình vừa post lên đã down rồi, cho mình thu hồi lại cái đó. Buồn ngủ post nhầm bản lỗi, mình post lại bản không lỗi rồi. Xin lỗi, cho mình xin thu hồi bản lỗi, down lại bản mới nè(Link down trang đầu đã được update).
Chỉ tại mình không có time rảnh phải làm buổi đêm nên mới ra nông nỗi này :((
 
Chỉnh sửa cuối:
cậu ơi xem phụ giúp tớ tích hợp map tớ ok lắm có điều chơi muti player là desysnc(disconnect ai mua đồ) :|
 
bạn vươngkkk hay ai đó cho mình hỏi cái này với. vd cái RawID cũ của cái item đó là "gsou" thì khi mình copy cái đó ra để chỉnh ability thì nó thêm ID là:"l0001gsou" vậy khi mình ghi nó trong code cũng y chang cái mã của item mình copy ra là "l0001sgou" hả. vậy mình muốn thêm item, này vào hệ thống thì mình sẽ gõ thê này hả
set grp = NewGrpRecipe('ciri',0)
set r = Recipe.create()
call Add2RecipeWithNum('rin1''l001gsou',1,r)
call grp.addRecipe(integer(r))
đây là item thành phẩm là ciri số lượng 1. cần 1 rin1 và 1 l0001gsou. đúng chưa nhỉ ;;)
 
^ À Với Object mới tạo, như trường hợp của bạn là "l001:sgou" thì khi vào code chỉ cần ghi là I001 là phần ở trước dấu : thôi

^^ ừ mình sẽ coi lại. Cám ơn bạn đã dùng system mình
 
^^^
Những gì cần sửa rất đơn giản. Thay function Init ở cuối cùng của recipe item system trigger = cái như sau
PHP:
private function Init takes nothing returns nothing
local integer index = 0
local trigger t = CreateTrigger()
    loop
    
        if GetPlayerSlotState(Player(index)) == PLAYER_SLOT_STATE_PLAYING then
            call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_PICKUP_ITEM, null)
        endif
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddAction(t, function Trig_1_Actions)
    set index = 0
    set t = CreateTrigger()
    loop
        if GetPlayerSlotState(Player(index)) == PLAYER_SLOT_STATE_PLAYING then
            call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null)
        endif
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddAction(t, function Trig_2_Actions)
endfunction

Đã update demo map ở trang đầu
 
Chỉnh sửa cuối:
vương ơi. có lỗi rồi đây. sửa đi nhá. mình thấy sys của bạn rất hay. nhưng còn lỗi nè. vd Ring+2 armor x2 => ring+4 armor. nhưng khi vứt ra đất nó lại thành 2 cái ring +2 thế là thế nào. nó vứt ra đất phải là ring +4 chứ. sao lịa là 2 cái +2 :-j. cái này hay nữa nè :d. VD 2 cái ring+2 nhập lại thành ring +4. xong vứt ra đất thành 2 ring +2. lượm 2 ring+2 lên nó lại không nhập thành ring +4 nữa :-j
 
Back
Top