Menu
CoddyTech

Tung xúc xắc độ hiếm

Bài học 10 trên 20 trong khóa học Trò chơi Roblox: mô phỏng thú cưng của Coddy.

Một quả trứng không phải lúc nào cũng cho ra Mèo. Settings.Pets liệt kê mọi thú cưng cùng Chance trên 100 (Mèo 45, Chó 30, Thỏ 15, Cáo 8, Rồng 2), độ hiếm và sức mạnh.

Phép chọn có trọng số: chọn một số từ 0 đến 100, sau đó lần lượt trừ xác suất của từng thú cưng trong danh sách. Thú cưng khiến kết quả giảm xuống 0 hoặc thấp hơn sẽ thắng, vì vậy thú cưng có xác suất 45 sẽ thắng trung bình 45 lần trong 100 lượt:

local roll = math.random() * 100
for _, info in Settings.Pets do
	roll -= info.Chance
	if roll <= 0 then
		return info.Name
	end
end

Thú cưng vừa nở cũng mang các thuộc tính Rarity và Power. Một bảng lưu thú cưng theo tên (petInfo["Fox"]) giúp tìm chúng nhanh chóng.

challenge icon

Thử thách

Trung bình

Chọn ngẫu nhiên thú cưng nở ra dựa trên Chance của từng thú cưng.

  1. Tạo petInfo: dùng Settings.Pets làm dữ liệu được lập chỉ mục theo Name.
  2. Trong givePet, đặt các thuộc tính Rarity và Power từ petInfo[name].
  3. Viết rollPet() để chọn ngẫu nhiên có trọng số, rồi cho nở thú cưng từ rollPet() thay vì Cat; lệnh in ra tên thú cưng vừa nở.

Nhấn Chơi rồi cho nở vài thú cưng: thỉnh thoảng Output sẽ hiện tên một thú cưng khác. Sau đó nhấn Kiểm tra.

Tự làm thử

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)

local remotes = game.ReplicatedStorage.Remotes
local piles = workspace.Piles
local pileSpot = {} -- mỗi đống xu -> vị trí của đống xu đó
local lastHit = {} -- mỗi người chơi -> thời điểm họ đánh lần gần nhất

print("A Meadow pile gives " .. Settings.PileValue .. " coins")

-- Thú cưng: một StringValue trong thư mục Pets của người chơi, lưu tên thú cưng
local function givePet(player, name)
	local pet = Instance.new("StringValue")
	pet.Name = "Pet"
	pet.Value = name
	pet.Parent = player.Pets
	return pet
end

-- Mỗi người chơi có Coins trên bảng xếp hạng
Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local coins = Instance.new("IntValue")
	coins.Name = "Coins"
	coins.Parent = leaderstats

	-- những thú cưng họ sở hữu
	local pets = Instance.new("Folder")
	pets.Name = "Pets"
	pets.Parent = player
end)

-- Đống xu tại một vị trí: bản sao của ServerStorage.CoinPile, với máu
-- và giá trị là các thuộc tính (attributes)
local function spawnPile(spot)
	local pile = ServerStorage.CoinPile:Clone()
	pile.Position = spot.Position
	pile:SetAttribute("MaxHealth", Settings.PileHealth)
	pile:SetAttribute("Health", Settings.PileHealth)
	pile:SetAttribute("Value", Settings.PileValue)
	pile.HealthGui.Label.Text = pile:GetAttribute("Health") .. "/" .. pile:GetAttribute("MaxHealth")
	pileSpot[pile] = spot
	pile.Parent = piles
	return pile
end

-- Mỗi cú đánh làm đống xu mất 1 máu;
-- khi máu về 0, đống xu vỡ và trả số xu bằng giá trị của nó
local function hitPile(player, pile)
	local health = pile:GetAttribute("Health") - 1
	if health > 0 then
		pile:SetAttribute("Health", health)
		pile.HealthGui.Label.Text = health .. "/" .. pile:GetAttribute("MaxHealth")
		return
	end
	player.leaderstats.Coins.Value += pile:GetAttribute("Value")
	local spot = pileSpot[pile]
	pileSpot[pile] = nil
	pile:Destroy()
	-- vài giây sau, một đống xu mới xuất hiện ở cùng vị trí
	task.delay(Settings.RespawnTime, spawnPile, spot)
end

-- Mỗi vị trí trong Meadow có một đống xu
for _, spot in workspace.Zones.Meadow.Spawns:GetChildren() do
	spawnPile(spot)
end

-- Máy khách yêu cầu đánh một đống xu. Đừng tin máy khách: bất kỳ ai cũng có thể kích hoạt
-- remote này với bất kỳ dữ liệu nào, từ bất kỳ đâu, nhanh tùy ý.
remotes.Hit.OnServerEvent:Connect(function(player, pile)
	-- đống xu có thật
	if typeof(pile) ~= "Instance" or pile.Parent ~= piles then
		return
	end
	-- trong tầm với
	local character = player.Character
	local root = character and character:FindFirstChild("HumanoidRootPart")
	if not root or (root.Position - pile.Position).Magnitude > Settings.Reach then
		return
	end
	-- không quá nhanh
	local now = time()
	if lastHit[player] and now - lastHit[player] < Settings.HitCooldown then
		return
	end
	lastHit[player] = now
	hitPile(player, pile)
end)

-- Thêm bài học 10: Rarity Rolls vào đây

-- Ấp trứng: tương tác với trứng và trả bằng xu
workspace.Egg.ProximityPrompt.Triggered:Connect(function(player)
	local coins = player.leaderstats.Coins
	if coins.Value < Settings.EggPrice then
		return
	end
	coins.Value -= Settings.EggPrice
	local name = "Cat"
	givePet(player, name)
	print(player.Name .. " hatched a " .. name)
end)

Tất cả bài học trong Trò chơi Roblox: mô phỏng thú cưng

Tự luyện tập: Playground Roblox