Đầu tiên, cho phép tôi xin lỗi, bởi vì đây sẽ là một bài viết khá dài. Tôi đã đưa ra chủ đề này rất nhiều suy nghĩ, và thậm chí đã thử nghiệm các khái niệm và triển khai trước đó .
Khi tôi tưởng tượng một bảng loot, tôi luôn nghĩ về một cái gì đó giống như cách World of Warcraft thực hiện chúng. Dưới đây là một ví dụ hình ảnh:
Bây giờ, chỉ sử dụng các tín hiệu trực quan, khi có thể phân tích khá nhiều cách thức hoạt động của hệ thống loot, nhưng chúng ta cũng hãy tiếp tục và sử dụng một số thống kê của Wowhead để hiểu rõ hơn về những gì chúng ta đang giải quyết. Đây là một giả lập nhanh chóng:
Như bạn có thể thấy, hệ thống loot mà World of Warcraft sử dụng khá năng động. Nó không chính xác là một roulette, nhưng có thể, ở cấp độ cơ sở, giống như một trong những cách. Lần thực hiện đầu tiên của tôi về Bảng Loot đã tránh được khái niệm roulette và thậm chí là một thợ cơ khí (điều này mang lại xác suất cao hơn cho việc lấy từ bàn và để lại những người khác). Tôi không thích ý tưởng cân vật phẩm trong tự nhiên này. Vì vậy, tôi đã làm một cái gì đó như thế này:
Bảng Loot này là một "Danh sách". Về cơ bản, tôi sẽ lặp qua từng mục, kiểm tra xác suất của nó và nếu thành công, tôi sẽ thêm nó vào danh sách các giọt. Điều này hoạt động tốt trên lý thuyết, nhưng tôi đã nhanh chóng nhận thấy một lỗ hổng chết người trong hệ thống.
Xem xét đầu ra này:
Ore_Copper x1
Nugget_Copper x2
Gem_Diamond x1
Gem_Emerald x1
Gem_Topaz x1
Đó là một sự phóng đại, nhưng nếu bạn nhìn vào cấu trúc cơ bản thì hoàn toàn có thể ... nhưng nếu chúng ta không muốn bỏ 4 loại đá quý thì sao? Ngoài ra, xác suất tập thể của các viên đá quý cũng khiến bạn thực sự được đảm bảo nhận được ít nhất một, bởi vì bạn có 10% * 5 cơ hội để có được một. Bây giờ, điều này có thể ổn cho một trò chơi, nhưng đó không phải là những gì tôi dự định. Tôi muốn có khả năng thả đá quý, nhưng chỉ có một cơ hội. Tôi muốn xác suất nhận được một viên đá quý chính xác là 10%. Vì vậy, làm thế nào để chúng tôi sửa lỗi này? Đây là những gì tôi nghĩ ra:
Vậy chuyện gì đang xảy ra bây giờ? Về cơ bản chúng tôi đã xây dựng một hệ thống roulette. Thay vì một bộ sưu tập trực tiếp của LootTableItem
s, giờ đây chúng tôi trì hoãn các mục thành các bộ sưu tập độc lập. LootTableList
S. Mỗi danh sách có xác suất riêng, giống như bản gốc của tôi LootTable
, nhưng bây giờ chúng tôi có thể sắp xếp thành công các mục vào "nhóm" của riêng mình trong một nhóm LootTable
. Nếu chúng tôi muốn một mặt hàng ít hiếm hơn một mặt hàng khác, chúng tôi chỉ cần thêm các trường hợp bổ sung vào mong muốn LootTableList
. Sau đó, khi tôi LootTable
đang chạy thuật toán của nó, nó sẽ chọn một mục từ LootTableList
. Điều này là tuyệt vời, nhưng nó cũng đưa ra một vấn đề khác. Điều gì sẽ xảy ra nếu tôi muốn tất cả các mục trong một LootTableList
bị rơi, hoặc có cơ hội rơi? Vâng, tôi đã đi trước và thêm một lĩnh vực, được gọi làCollectAll
. Khi trường này được chọn, nó sẽ tránh chọn một mục và thay vào đó chọn tất cả các mục trong LootTableList
.
Sau khi lên kế hoạch cho tất cả những điều này và làm bài tập về nhà của tôi về chủ đề này, tôi đã đến để tạo ra loại LootTable này. Tôi cũng khá chắc chắn rằng đây cũng là loại LootTable mà World of Warcraft đang sử dụng, hoặc ít nhất là về mặt khái niệm chúng rất gần gũi. Đây là mã:
using System;
using System.Collections.Generic;
using System.Linq;
using GrimoireDevelopmentKit.Framework.Interfaces;
using GrimoireDevelopmentKit.Framework.Maths;
using GrimoireDevelopmentKit.Framework.Utilities;
namespace GrimoireDevelopmentKit.Framework.Collections
{
[Serializable]
public class LootTable : Dictionary<string, LootTableList>, ICopy<LootTable>
{
public string Identifier { get; set; }
public AdvancedRandom Random { get; set; }
public int TotalItems
{
get
{
int total = 0;
foreach (LootTableList list in this.Values)
{
total += list.Values.Count;
}
return total;
}
}
public LootTable(string identifier = null)
: this(identifier, new AdvancedRandom())
{
}
public LootTable(string identifier, AdvancedRandom random)
{
Identifier = identifier;
Random = random;
}
public void Add(LootTableList list)
{
if (!Contains(list))
{
Add(list.Identifier, list);
}
else
{
throw new ArgumentException("Key: '" + list.Identifier + "' already exists!");
}
}
public bool Remove(LootTableList list)
{
return Remove(list.Identifier);
}
public bool Contains(string listIdentifier)
{
return ContainsKey(listIdentifier);
}
public bool Contains(LootTableList list)
{
return Contains(list.Identifier);
}
public List<LootTableResult> Next()
{
Range probabilityScope = new Range(0, 100);
List<LootTableResult> drops = new List<LootTableResult>(TotalItems);
foreach (LootTableList list in Values)
{
bool success = Random.NextRange(probabilityScope) <= list.Probability;
if (success)
{
if (list.CollectAll)
{
foreach (LootTableItem item in list.Values)
{
int quantity = Random.NextRange(item.Quantity);
if(quantity > 0)
{
drops.Add(new LootTableResult(item.Identifier, quantity));
}
}
}
else
{
LootTableItem item = list.ElementAt(Random.NextInteger(0, list.Count)).Value;
int quantity = Random.NextRange(item.Quantity);
if(quantity > 0)
{
drops.Add(new LootTableResult(item.Identifier,quantity));
}
}
}
}
return drops;
}
public void Copy(LootTable other)
{
this.Clear();
this.Identifier = other.Identifier;
this.Random = other.Random;
foreach (LootTableList list in other.Values)
{
this.Add(list.MakeCopy());
}
}
public LootTable MakeCopy()
{
LootTable copy = new LootTable();
copy.Copy(this);
return copy;
}
}
}
Câu hỏi của tôi:
Có một nền tảng khái niệm tốt hơn và hiện đại hơn mà tôi có thể sử dụng để đạt được loại bảng loot này không?
Có nhà phát triển trò chơi nào trên trang web này đã tạo ra Loot Bàn về bản chất này không? Tôi chỉ muốn biết liệu tôi có thể cải thiện khái niệm của mình không chỉ là mã mà còn là chính khái niệm đó. Tôi chắc chắn có nhiều điều có thể được thực hiện để cải thiện công việc của tôi. Tôi chỉ tìm kiếm lời khuyên từ những người có kinh nghiệm trong chủ đề này.
Tôi cũng có thể đăng triển khai của mình vào một dự án riêng nếu nó giúp mọi người giúp tôi . Trên thực tế, tôi nghĩ rằng tôi sẽ thực hiện nó ngay bây giờ trên thực tế.
BIÊN TẬP
Chỉ nhận ra rằng tôi đã quên mã số lượng Số lượng trong LootTableLists, nếu được mã hóa, sẽ cho phép LootTableList được thu thập từ nhiều lần trong cùng một lần thả.