Tôi không chắc liệu bạn có đang đọc cái này không nhưng tôi đã vật lộn với loại vấn đề này trong một thời gian dài.
Tôi đã thiết kế nhiều loại hệ thống ảnh hưởng khác nhau. Tôi sẽ nhanh chóng đi qua chúng bây giờ. Đây là tất cả dựa trên kinh nghiệm của tôi. Tôi không yêu cầu phải biết tất cả các câu trả lời.
Bộ điều chỉnh tĩnh
Loại hệ thống này chủ yếu dựa vào các số nguyên đơn giản để xác định bất kỳ sửa đổi nào. Ví dụ: +100 đến Max HP, +10 để tấn công, v.v. Hệ thống này cũng có thể xử lý phần trăm là tốt. Bạn chỉ cần đảm bảo rằng việc xếp chồng không vượt khỏi tầm kiểm soát.
Tôi không bao giờ thực sự lưu trữ các giá trị được tạo cho loại hệ thống này. Ví dụ: nếu tôi muốn hiển thị sức khỏe tối đa của một thứ gì đó, tôi sẽ tạo ra giá trị tại chỗ. Điều này ngăn chặn mọi thứ dễ bị lỗi và dễ hiểu hơn cho mọi người liên quan.
(Tôi làm việc trong Java vì vậy những gì tiếp theo là dựa trên Java nhưng nó sẽ hoạt động với một số sửa đổi cho các ngôn ngữ khác) Hệ thống này có thể dễ dàng được thực hiện bằng cách sử dụng enums cho các loại sửa đổi, sau đó là số nguyên. Kết quả cuối cùng có thể được đặt vào một số loại bộ sưu tập có các cặp khóa, giá trị theo thứ tự. Đây sẽ là tra cứu và tính toán nhanh, vì vậy hiệu suất rất tốt.
Nhìn chung, nó hoạt động rất tốt với chỉ cần sửa đổi tĩnh. Mặc dù, mã phải tồn tại ở những vị trí thích hợp cho các bộ sửa đổi được sử dụng: getAttack, getMaxHP, getMeleeDamage, v.v.
Trường hợp phương thức này thất bại (đối với tôi) là sự tương tác rất phức tạp giữa các buff. Không có cách nào thực sự dễ dàng để có tương tác ngoại trừ bằng cách tăng cường một chút. Nó có một số khả năng tương tác đơn giản. Để làm điều đó, bạn phải thực hiện một sửa đổi cho cách bạn lưu trữ các bộ sửa đổi tĩnh. Thay vì sử dụng enum làm khóa, bạn sử dụng Chuỗi. Chuỗi này sẽ là tên Enum + biến phụ. 9 trong số 10 lần, biến phụ không được sử dụng, do đó bạn vẫn giữ tên enum làm khóa.
Hãy làm một ví dụ nhanh: Nếu bạn muốn có thể sửa đổi thiệt hại chống lại các sinh vật bất tử, bạn có thể có một cặp theo thứ tự như thế này: (DAMAGE_Undead, 10) DAMAGE là Enum và Undead là biến phụ. Vì vậy, trong quá trình chiến đấu, bạn có thể làm một cái gì đó như:
dam += attacker.getMod(Mod.DAMAGE + npc.getRaceFamily()); //in this case the race family would be undead
Dù sao, nó hoạt động khá tốt và nhanh chóng. Nhưng nó thất bại ở các tương tác phức tạp và có mã đặc biệt trên mạng ở khắp mọi nơi. Ví dụ, hãy xem xét tình huống của 25% cơ hội để dịch chuyển tức thời trên cái chết. Đây là một khu phức hợp khá tốt. Hệ thống trên có thể xử lý nó, nhưng không dễ dàng, vì bạn cần những điều sau đây:
- Xác định xem người chơi có mod này không.
- Ở đâu đó, có một số mã để thực hiện dịch chuyển tức thời, nếu thành công. Vị trí của mã này là một cuộc thảo luận trong chính nó!
- Lấy dữ liệu đúng từ bản đồ Mod. Giá trị có nghĩa là gì? Có phải đó là căn phòng nơi họ dịch chuyển quá không? Điều gì nếu một người chơi có hai mod dịch chuyển tức thời trên chúng ?? Số tiền sẽ không được cộng lại với nhau chứ ?????? SỰ THẤT BẠI!
Vì vậy, điều này đưa tôi đến người tiếp theo của tôi:
Hệ thống Buff phức tạp cuối cùng
Tôi đã từng cố gắng tự viết một MMORPG 2D. Đây là một sai lầm khủng khiếp nhưng tôi đã học được rất nhiều!
Tôi viết lại hệ thống ảnh hưởng 3 lần. Cái đầu tiên sử dụng một biến thể ít mạnh mẽ hơn ở trên. Điều thứ hai là những gì tôi sẽ nói về.
Hệ thống này có một loạt các lớp cho mỗi sửa đổi, vì vậy những thứ như: ChangeHP, ChangeMaxHP, ChangeHPByPercent, ChangeMaxByPercent. Tôi đã có một triệu người trong số họ - thậm chí cả những thứ như TeleportOnDeath.
Các lớp học của tôi có những thứ sẽ làm như sau:
- áp dụng hiệu quả
- loại bỏ
- checkForInteraction <--- quan trọng
Tự áp dụng và xóa giải thích (mặc dù đối với những thứ như phần trăm, ảnh hưởng sẽ theo dõi mức độ tăng của HP bằng cách đảm bảo khi ảnh hưởng giảm đi, nó chỉ xóa số tiền được thêm vào. Đây là lỗi, lol, và tôi đã mất một thời gian dài để chắc chắn rằng nó đúng. Tôi vẫn không có cảm giác tốt về nó.).
Phương thức checkForInteraction là một đoạn mã phức tạp khủng khiếp. Trong mỗi lớp ảnh hưởng (ví dụ: ChangeHP), nó sẽ có mã để xác định xem điều này có nên được sửa đổi bởi ảnh hưởng đầu vào hay không. Vì vậy, ví dụ, nếu bạn có một cái gì đó như ....
- Buff 1: Gây 10 sát thương lửa khi tấn công
- Buff 2: Tăng 25% sát thương lửa.
- Buff 3: Tăng tất cả sát thương lửa lên 15.
Phương thức checkForInteraction sẽ xử lý tất cả những ảnh hưởng này. Để làm điều này, từng ảnh hưởng đến TẤT CẢ những người chơi gần đó phải được kiểm tra !! Điều này là do loại ảnh hưởng mà tôi đã xử lý với nhiều người chơi trên một phạm vi của một khu vực. Điều này có nghĩa là mã KHÔNG BAO GIỜ có bất kỳ tuyên bố đặc biệt nào như trên - nếu chúng ta vừa mới chết, chúng ta nên kiểm tra dịch chuyển tức thời trên death chết. Hệ thống này sẽ tự động xử lý chính xác vào đúng thời điểm.
Cố gắng viết hệ thống này khiến tôi mất 2 tháng và đầu nổ tung nhiều lần. TUY NHIÊN, nó thực sự mạnh mẽ và có thể tạo ra một số thứ điên rồ - đặc biệt là khi bạn tính đến hai sự thật sau đây cho các khả năng trong trò chơi của tôi: 1. Họ có phạm vi mục tiêu (ví dụ: đơn, tự, chỉ nhóm, tự PB , Mục tiêu PB AE, AE được nhắm mục tiêu, v.v.). 2. Khả năng có thể có nhiều hơn 1 ảnh hưởng đến họ.
Như tôi đã đề cập ở trên, đây là hệ thống ảnh hưởng thứ 2 của trò chơi này. Tại sao tôi lại di chuyển khỏi đây?
Hệ thống này có hiệu suất tồi tệ nhất tôi từng thấy! Nó rất chậm vì nó phải kiểm tra rất nhiều cho từng thứ đang diễn ra. Tôi đã cố gắng cải thiện nó, nhưng coi đó là một thất bại.
Vì vậy, chúng tôi đến phiên bản thứ ba của tôi (và một loại hệ thống buff khác):
Lớp ảnh hưởng phức tạp với xử lý
Vì vậy, đây là sự kết hợp của hai yếu tố đầu tiên: Chúng ta có thể có các biến tĩnh trong một lớp Ảnh hưởng có chứa nhiều chức năng và dữ liệu bổ sung. Sau đó, chỉ cần gọi trình xử lý (đối với tôi, khá nhiều phương thức tiện ích tĩnh thay vì các lớp con cho các hành động cụ thể. Nhưng tôi chắc chắn bạn có thể đi với các lớp con cho các hành động nếu bạn cũng muốn) khi chúng tôi muốn làm gì đó.
Lớp Affect sẽ có tất cả những thứ tốt đẹp, như các loại mục tiêu, thời lượng, số lần sử dụng, cơ hội để thực hiện, v.v.
Chúng tôi vẫn sẽ phải thêm các mã đặc biệt để xử lý các tình huống, ví dụ, dịch chuyển tức thời về cái chết. Chúng tôi vẫn sẽ phải kiểm tra điều này trong mã chiến đấu bằng tay, và sau đó nếu nó tồn tại, chúng tôi sẽ nhận được một danh sách các ảnh hưởng. Danh sách ảnh hưởng này chứa tất cả các ảnh hưởng hiện đang được áp dụng đối với người chơi liên quan đến dịch chuyển tức thời khi chết. Sau đó, chúng tôi sẽ chỉ nhìn vào từng người và kiểm tra xem liệu nó đã thực hiện và đã thành công chưa (Chúng tôi sẽ dừng lại ở lần đầu tiên thành công). Nó đã thành công, chúng tôi chỉ cần gọi người xử lý để giải quyết việc này.
Tương tác có thể được thực hiện, nếu bạn muốn quá. Chỉ cần viết mã để tìm kiếm các buff cụ thể trên người chơi / v.v. Bởi vì nó có hiệu suất tốt (xem bên dưới), nên nó khá hiệu quả để làm điều đó. Nó chỉ cần xử lý phức tạp hơn và như vậy.
Vì vậy, nó có rất nhiều hiệu suất của hệ thống đầu tiên và vẫn còn rất nhiều phức tạp như hệ thống thứ hai (nhưng không nhiều AS). Trong Java ít nhất, bạn có thể thực hiện một số điều khó khăn để có được hiệu năng của gần như lần đầu tiên trong các trường hợp MOST (ví dụ: có bản đồ enum ( http://docs.oracle.com/javase/6/docs/api/java /util/EnumMap.html ) với Enums là các khóa và ArrayList ảnh hưởng như các giá trị. Điều này cho phép bạn xem nếu bạn nhanh chóng có ảnh hưởng [vì danh sách sẽ là 0 hoặc bản đồ sẽ không có enum] và không có để liên tục lặp lại các danh sách ảnh hưởng của người chơi mà không có lý do. Tôi không ngại lặp đi lặp lại ảnh hưởng nếu chúng ta cần chúng vào lúc này. Tôi sẽ tối ưu hóa sau nếu nó trở thành vấn đề).
Tôi hiện đang mở lại (viết lại trò chơi bằng Java thay vì cơ sở mã FastROM ban đầu) MUD của tôi đã kết thúc vào năm 2005 và gần đây tôi đã gặp phải cách tôi muốn triển khai hệ thống buff của mình? Tôi sẽ sử dụng hệ thống này vì nó hoạt động tốt trong trò chơi thất bại trước đây của tôi.
Vâng, hy vọng ai đó, ở đâu đó, sẽ tìm thấy một vài trong số những hiểu biết hữu ích.