Tin tức về thú cưng hiếm
Bài học 18 trên 20 trong khóa học Trò chơi Roblox: mô phỏng thú cưng của Coddy.
Khi có người ấp nở một thú cưng Legendary, cả máy chủ nên biết. FireAllClients kích hoạt một RemoteEvent trên máy khách của mọi người chơi cùng lúc:
-- máy chủ
remotes.Announce:FireAllClients(player.Name, name)
-- máy khách
remotes.Announce.OnClientEvent:Connect(function(who, pet)
end)Mỗi máy khách hiển thị tin này trên Banner trong HUD của mình trong vài giây. OnClientEvent nhận chính xác nội dung máy chủ gửi: phía này không thêm người chơi nào.
Thử thách
KhóThông báo cho mọi người khi có thú cưng Legendary.
- Trong
PetServer, giữ lạilocal pet = givePet(...); nếuRaritycủa thú cưng làLegendary, hãy gọiremotes.Announce:FireAllClients(player.Name, name). - Trong
PetClient,remotes.Announce.OnClientEventnhận(who, pet): đặthud.Banner.Textthànhwho .. " hatched a " .. pet .. "!", hiển thị biểu ngữ, chờ 4 giây rồi ẩn đi.
Nhấn Chơi rồi ấp trứng: một con Dragon, với tỷ lệ 1 trứng trong 50, sẽ hiện biểu ngữ màu vàng trên mọi màn hình. Sau đó nhấn Kiểm tra.
Tự làm thử
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local RunService = game:GetService("RunService")
local Settings = require(game.ReplicatedStorage.Settings)
local remotes = game.ReplicatedStorage.Remotes
local piles = workspace.Piles
local petParts = workspace.PetParts
local pileSpot = {} -- mỗi đống xu -> vị trí đặt đống xu đó
local lastHit = {} -- mỗi người chơi -> thời điểm họ đánh lần cuối
print("A Meadow pile gives " .. Settings.PileValue .. " coins")
-- Settings.Pets theo tên
local petInfo = {}
for _, info in Settings.Pets do
petInfo[info.Name] = info
end
-- Thú cưng: một StringValue trong thư mục Pets của người chơi, lưu tên thú cưng, cùng với
-- độ hiếm và sức mạnh dưới dạng thuộc tính
local function givePet(player, name, equipped)
local info = petInfo[name]
local pet = Instance.new("StringValue")
pet.Name = "Pet"
pet.Value = name
pet:SetAttribute("Rarity", info.Rarity)
pet:SetAttribute("Power", info.Power)
pet:SetAttribute("Equipped", equipped)
pet.Parent = player.Pets
return pet
end
-- số thú cưng người chơi đang cho ra ngoài
local function equippedCount(player)
local count = 0
for _, pet in player.Pets:GetChildren() do
if pet:GetAttribute("Equipped") then
count += 1
end
end
return count
end
-- sức mạnh thú cưng cộng thêm vào mỗi cú đánh của người chơi
local function petPower(player)
local power = 0
for _, pet in player.Pets:GetChildren() do
if pet:GetAttribute("Equipped") then
power += pet:GetAttribute("Power")
end
end
return power
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, có máu
-- và giá trị dưới dạng thuộc tính
local function spawnPile(spot)
local desert = spot.Parent.Parent.Name == "Desert"
local health = desert and Settings.DesertHealth or Settings.PileHealth
local pile = ServerStorage.CoinPile:Clone()
pile.Position = spot.Position
pile:SetAttribute("MaxHealth", health)
pile:SetAttribute("Health", health)
pile:SetAttribute("Value", desert and Settings.DesertValue or Settings.PileValue)
pile:SetAttribute("Zone", spot.Parent.Parent.Name)
pile.HealthGui.Label.Text = pile:GetAttribute("Health") .. "/" .. pile:GetAttribute("MaxHealth")
pileSpot[pile] = spot
pile.Parent = piles
return pile
end
-- Mỗi cú đánh trừ 1 máu của đống xu, cộng thêm sức mạnh của thú cưng;
-- Khi máu về 0, đống xu vỡ và trao số xu bằng giá trị của nó
local function hitPile(player, pile)
local health = pile:GetAttribute("Health") - (1 + petPower(player))
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 mỗi khu vực đều có một đống xu
for _, zone in workspace.Zones:GetChildren() do
for _, spot in zone.Spawns:GetChildren() do
spawnPile(spot)
end
end
-- Máy khách yêu cầu đánh đố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 dữ liệu bất kỳ, từ bất cứ đâ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
-- trong khu vực người chơi đã mở khóa
if pile:GetAttribute("Zone") == "Desert" and not player:GetAttribute("Desert") then
return
end
hitPile(player, pile)
end)
-- Chọn ngẫu nhiên theo trọng số: Chance của mỗi thú cưng (trên 100) là phần cơ hội của nó
local function rollPet()
local roll = math.random() * 100
for _, info in Settings.Pets do
roll -= info.Chance
if roll <= 0 then
return info.Name
end
end
return Settings.Pets[1].Name
end
-- Ấ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 = rollPet()
-- cho ra ngoài ngay nếu còn chỗ
local pet = givePet(player, name, equippedCount(player) < Settings.MaxEquipped)
print(player.Name .. " hatched a " .. name)
end)
-- Thú cưng đang theo chủ: mỗi con có một bộ phận trong thế giới game, nằm
-- thành hàng sau người chơi ở mỗi khung hình
local petModels = {} -- mỗi thú cưng -> bộ phận của nó trong thế giới game
RunService.Heartbeat:Connect(function()
for _, player in Players:GetPlayers() do
local root = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
local pets = player:FindFirstChild("Pets")
local slot = 0
for _, pet in pets and pets:GetChildren() or {} do
local model = petModels[pet]
if pet:GetAttribute("Equipped") and root then
slot += 1
if not model then
model = ServerStorage.PetModels[pet.Value]:Clone()
model.Parent = petParts
petModels[pet] = model
end
model.CFrame = root.CFrame * CFrame.new((slot - 2) * 3, -1.5, 4)
elseif model then
-- cất thú cưng đi: xóa bộ phận của nó
model:Destroy()
petModels[pet] = nil
end
end
end
end)
-- Client yêu cầu đưa thú cưng ra hoặc cất đi. Máy chủ kiểm tra: thú cưng
-- thuộc về người chơi và số thú cưng đang theo không vượt quá MaxEquipped.
remotes.Equip.OnServerEvent:Connect(function(player, pet)
if typeof(pet) ~= "Instance" or pet.Parent ~= player.Pets then
return
end
if pet:GetAttribute("Equipped") then
pet:SetAttribute("Equipped", false)
elseif equippedCount(player) < Settings.MaxEquipped then
pet:SetAttribute("Equipped", true)
end
end)
-- Cổng Desert: người chơi trả tiền một lần để mở cổng, nhưng cổng chỉ mở với người đó
workspace.Gate.ProximityPrompt.Triggered:Connect(function(player)
local coins = player.leaderstats.Coins
if player:GetAttribute("Desert") or coins.Value < Settings.GatePrice then
return
end
coins.Value -= Settings.GatePrice
player:SetAttribute("Desert", true)
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