Created
January 16, 2018 22:13
-
-
Save Aerodos12/3544832da9f5e8ff53c938ffec88534c to your computer and use it in GitHub Desktop.
Camos, KillService, Quest System, etc.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Camo = {} | |
local RunService = game:GetService("RunService") | |
local RemoteService = require(game.ReplicatedStorage.RemoteService) | |
Camo.__index = Camo | |
local CamoTypeFuncs = { | |
["Material"] = function(camo) | |
return typeof(camo.Image) == "EnumItem" and camo.Image.EnumType == Enum.Material | |
end; | |
["Texture"] = function(camo) | |
return typeof(camo.Image) == "string" and camo.Image:find("rbxassetid://") | |
end; | |
} | |
function Camo.new(...) | |
local self = {} | |
local args = {...} | |
local title = args[1] | |
if typeof(title) ~= "string" or not title then return nil end | |
self.Title = title | |
local image = args[2] | |
if (typeof(image) ~= "string" and typeof(image) ~= "EnumItem") or not image then return nil end | |
self.Image = image | |
local slotParts = {} | |
for i = 3, #args do | |
if args[i] and typeof(args[i]) == "string" then | |
slotParts[#slotParts+1] = args[i] | |
end | |
end | |
self.Slots = slotParts | |
self.ButtonConnection = nil | |
self.ExtraData = {} | |
return setmetatable(self,Camo) | |
end | |
function Camo:AddData(key,value) | |
self.ExtraData[key] = value | |
end | |
function Camo:ToReplicatedCamo() | |
local camo = {} | |
camo.Title = self.Title | |
camo.Image = self.Image | |
camo.Slots = self.Slots | |
return camo | |
end | |
function Camo.FromReplicatedCamo(camo) | |
return Camo.new(camo.Title,camo.Image,unpack(camo.Slots)) | |
end | |
function Camo:IsSlotPart(part) | |
local result = false | |
for _, slot in pairs(self.Slots) do | |
if slot == part.Name then | |
result = true | |
end | |
end | |
return result | |
end | |
function Camo:IsA(camoType) | |
return CamoTypeFuncs[camoType](self) | |
end | |
function Camo:Apply(gun) | |
if gun:IsA("Tool") and RunService:IsServer() then | |
if gun.Type.Value == "Blaster" then | |
if gun:FindFirstChild("CamoId") then | |
gun.CamoId.Value = self.Image | |
end | |
end | |
elseif gun:IsA("Model") then | |
if gun:FindFirstChild("Primary") then | |
for _, part in pairs(gun:GetChildren()) do | |
if part:IsA("BasePart") and self:IsSlotPart(part) then | |
if self:IsA("Texture") then | |
for _, texture in pairs(part:GetChildren()) do | |
if texture:IsA("Texture") then | |
texture.Texture = self.Image | |
end | |
end | |
elseif self:IsA("Material") then | |
part.Material = self.Image | |
if self.ExtraData["Color"] then | |
local camColor = self.ExtraData["Color"] | |
if typeof(camColor) == "BrickColor" then | |
part.BrickColor = self.ExtraData["Color"] | |
elseif typeof(camColor) == "Color3" then | |
part.Color = self.ExtraData["Color"] | |
end | |
end | |
end | |
end | |
end | |
end | |
elseif gun:IsA("Tool") and RunService:IsClient() then | |
RemoteService.send("Server","ChangeCamo",gun,self:ToReplicatedCamo()) | |
end | |
end | |
function Camo:CreateButton(name,player,weaponImage,weapon) | |
local CamoButton = game.ReplicatedStorage.DeploymentUIs.CamoButton:Clone() | |
CamoButton.Name = name | |
CamoButton.CamoTitle.Text = self.Title:upper() | |
CamoButton.CamoPreview.Image = self.Image | |
self.ButtonConnection = CamoButton.UseButton.MouseButton1Click:connect(function() | |
print("Setting Camo...") | |
self:Apply(weaponImage) | |
self:Apply(weapon) | |
end) | |
return CamoButton | |
end | |
return Camo |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local POW = math.pow | |
local RANDOM = math.random | |
local GetMod = require | |
local OBJ = Instance.new | |
local WS = workspace | |
local FLOOR = math.floor | |
local RepStore = game.ReplicatedStorage | |
local RPGM = GetMod(RepStore.RPGMathProvider) | |
local AvailableArmor = GetMod(WS.Settings.AvailableArmor) | |
local ForcePowers = require(game.Workspace.Settings.ForcePowers) | |
local ForceLib = GetMod(RepStore.ForceLib) | |
local SaveGame = GetMod(WS.Settings.SaveGame) | |
local ArmorSlots = require(game.ReplicatedStorage.ArmorSlots) | |
local MarketService = GetMod(game.ReplicatedStorage.MarketService) | |
local AnalyticsService = require(game.ReplicatedStorage.AnalyticsService) | |
local KillService = require(game.ServerScriptService.KillService) | |
local TSS = require(script.Parent.ToolStoreService) | |
local RSEED = math.randomseed | |
local TICK = tick | |
local V3 = Vector3.new | |
local CF = CFrame.new | |
local CSEQ = ColorSequence.new | |
local BC = BrickColor.new | |
local DSS = game:GetService("DataStoreService") | |
local DS = game:GetService('Debris') | |
local Types = { | |
["string"] = "StringValue", | |
["boolean"] = "BoolValue", | |
["number"] = "IntValue" | |
} | |
local LoadoutDefaults = {} | |
local CurrentSlot = {} | |
local CurrentXP = {} | |
local Settings = {} | |
local teams = game.Teams:GetTeams() | |
for _, characterClass in pairs(teams) do | |
LoadoutDefaults[characterClass.Name] = require(characterClass.LoadoutDefaults) | |
end | |
local EquipmentInventory = require(game.ReplicatedStorage.EquipmentInventory) | |
local SetttingsCache = require(game.ReplicatedStorage.SettingsCache) | |
local EquipmentCache = {} | |
local PlayerLoadouts = {} | |
local PlayerSquads = {} | |
local Slots = game.Workspace.Stages | |
local TutorialService = require(game.ReplicatedStorage.TutorialService) | |
local Soldier = require(game.ReplicatedStorage.Soldier) | |
local SquadClass = require(game.ReplicatedStorage.Squad) | |
local Squads = {} | |
RSEED(TICK()) | |
local SaberfrontDB = require(game.ReplicatedStorage.SaberfrontDBService) | |
local DataManager = { | |
PData = DSS:GetDataStore(SaveGame.DSName), | |
SoldierData = SaberfrontDB:GetDatabase("Soldiers"); | |
HighScores = DSS:GetOrderedDataStore("HighScores"); | |
Settings = DSS:GetDataStore("UserSettings"); | |
MarketplaceData = DSS:GetDataStore("MarketStats"); | |
} | |
local UnitData = require(game.ReplicatedStorage.UnitPrices) | |
DataManager.ignoreModel = workspace.mobIgnore | |
local RemoteService = GetMod(game.ReplicatedStorage.RemoteService) | |
local BindableService = require(game.ReplicatedStorage.BindingService)() | |
function DataManager:UpgradePlayerByXP(Others,PerLevel,Caps,player, Starting, XP, level) | |
DataManager:SaveHighScore(player,"XP") | |
if XP.Value < 0 then | |
XP.Value = CurrentXP[player.UserId] | |
end | |
if XP.Value >= RPGM.EXP[Others.XPType:lower()](PerLevel,Others,level.Value) and level.Value < Caps.LevelCap then | |
XP.Value = XP.Value - RPGM.EXP[Others.XPType:lower()](PerLevel,Others,level.Value) | |
level.Value = level.Value + 1 | |
player.attributes.APs.Value = player.attributes.APs.Value + FLOOR((level.Value / PerLevel.LevelsToGainPoints) * Others.PointGainIncrement) | |
end | |
end | |
local Fireworks = GetMod(WS.Settings.Fireworks) | |
function DataManager:Rocket(char) | |
local r = OBJ('Part') | |
r.Size = V3(0.2,0.2,0.2) | |
r.Position = (char.Head.CFrame + V3(0,2,0)).p | |
r.Parent = WS | |
r.CFrame = char.Head.CFrame + V3(0,2,0) | |
local speed = RANDOM(Fireworks.VelocityMin,Fireworks.VelocityMax) | |
r.Anchored = false | |
r.CanCollide = false | |
r.Transparency = 1 | |
local BF = OBJ("BodyForce") | |
BF.force = V3(0, r:GetMass() * 196.2, 0) | |
BF.Parent = r | |
local trail = script:WaitForChild('Trail'):Clone() | |
trail.Parent = r | |
trail.Enabled = true | |
wait(0.03) | |
local spread = char.Head.Position + V3(RANDOM(-5,5),Fireworks.Height + RANDOM(-Fireworks.HeightSpread,Fireworks.HeightSpread),RANDOM(-5,5)) | |
r.Velocity = (char.Head.Position - spread).unit * -speed | |
wait(RANDOM(Fireworks.DelayMin,Fireworks.DelayMax)) | |
r.Anchored = true | |
trail:Destroy() | |
local explosion = Fireworks.Explosions[RANDOM(1,#Fireworks.Explosions)]:clone() | |
explosion.Parent = r | |
local scolor = Fireworks.StartColors[RANDOM(1,#Fireworks.StartColors)] | |
local ecolor = Fireworks.EndColors[RANDOM(1,#Fireworks.EndColors)] | |
explosion.Color = CSEQ(scolor,ecolor) | |
wait(0.03) | |
explosion:Emit(RANDOM(300,350)) | |
DS:AddItem(r,explosion.Lifetime.Max) | |
end | |
function DataManager:TryTransaction(dataStoreFunction) | |
local tries = 0 | |
local success = true | |
local err = nil | |
local data = nil | |
repeat | |
tries = tries + 1 | |
success, err = pcall(function() data = dataStoreFunction() end) | |
if not success then print(err) wait(1) end | |
until tries == SaveGame.DataStoreRetries or success | |
if not success then | |
warn('Could not access DataStore! Warn players that their data might not get saved!') | |
end | |
return success, data | |
end | |
function DataManager:ConvertToCharacterAppearance(data,plr,chr,CAD) | |
chr["Body Colors"].HeadColor = BC(CAD.SkinColor.Value) | |
chr["Body Colors"].LeftArmColor = BC(CAD.SkinColor.Value) | |
chr["Body Colors"].RightArmColor = BC(CAD.SkinColor.Value) | |
chr["Body Colors"].LeftLegColor = BC(CAD.SkinColor.Value) | |
chr["Body Colors"].RightLegColor = BC(CAD.SkinColor.Value) | |
chr:WaitForChild("Shirt",600).ShirtTemplate = CAD.ShirtTemplate.Value | |
chr:WaitForChild("Hair").Handle.BrickColor = BC(CAD.HairColor.Value) | |
chr.Pants.PantsTemplate = CAD.PantsTemplate.Value | |
end | |
function DataManager:GetSquadReplicated(player) | |
local squad = {} | |
for _, squadMate in pairs(Squads[player.UserId]) do | |
squad[#squad+1] = squadMate:ToReplicatedSquadmate() | |
end | |
return squad | |
end | |
function DataManager:UpgradePlayerByLevel(player, XP, level) | |
if player.Character~=nil then | |
AnalyticsService.RecordLevelProgression(player,level.Value,XP.Value) | |
for i = 1,5 do | |
DataManager:Rocket(player.Character) | |
wait(Fireworks.ShotCooldown) | |
end | |
end | |
end | |
function DataManager:GetSaveGame(player,pvp) | |
local BService = require(game.ReplicatedStorage.BindingService)() | |
local save = { | |
Lvl = player.leaderstats.Lvl.Value, | |
XP = player.leaderstats.XP.Value, | |
Credits = player.leaderstats.Credits.Value, | |
CharacterName = player.CharacterName.Value, | |
PVPScore = pvp.Value, | |
InPvP = player.Stats.InPvP.Value, | |
Team = player.Team.Name, | |
Attributes = { | |
Strength = player.attributes.Strength.Value, | |
Constitution = player.attributes.Constitution.Value, | |
Intelligence = player.attributes.Intelligence.Value, | |
Dexterity = player.attributes.Dexterity.Value | |
}; | |
KDR = { | |
Kills = KillService.TotalKills[player.UserId]; | |
}; | |
AttributePoints = player.attributes.APs.Value; | |
AlreadyCustomized = player.AlreadyCustomized.Value; | |
ForceColor = player.ForceColor.Value.Name | |
} | |
save.Achievements = BService.fetch("GetCompletedAchievements",player) | |
save.Traits = BService.fetch("GetAcquiredTraits",player); | |
save.i8Mode = player.i8Mode.Value | |
save.DeploymentMode = player.DeploymentMode.Value | |
save.EquippedArmor = { | |
hasArmorOn = EquipmentCache[player.UserId].On; | |
ArmorType = EquipmentCache[player.UserId].Type; | |
CurrentPlacement = EquipmentCache[player.UserId].CurrentPlacement; | |
}; | |
save.Loadout = PlayerLoadouts[player.UserId] | |
save.Squad = DataManager:GetSquadReplicated(player) | |
save.Armor = {} | |
for _,ArmorSelection in pairs(AvailableArmor) do | |
save.Armor['Unlocked'..ArmorSelection] = player.UnlockedArmor:FindFirstChild('Unlocked'..ArmorSelection).Value | |
end | |
save.CA = { | |
HairColor = player.CharacterAppearanceData.HairColor.Value, | |
SkinColor = player.CharacterAppearanceData.SkinColor.Value, | |
PantsTemplate = player.CharacterAppearanceData.PantsTemplate.Value, | |
ShirtTemplate = player.CharacterAppearanceData.ShirtTemplate.Value, | |
} | |
return save | |
end | |
function DataManager:NumPlayersUnCustomized() | |
local num = 0 | |
for _, player in pairs(game.Players:GetPlayers()) do | |
if player:FindFirstChild("AlreadyCustomized") then | |
if not player.AlreadyCustomized.Value then | |
num = num + 1 | |
end | |
end | |
end | |
return num | |
end | |
function DataManager:saveScores(player,pvp) | |
local Starting = require(game.Workspace.Settings.Starting) | |
local success = DataManager:TryTransaction(function() | |
local save = DataManager:GetSaveGame(player,pvp) | |
local saveGame, marketData = DataManager:GetSavedData(player,Starting) | |
local saved, err | |
if DataManager.PData:GetAsync(player.Name .. "-id") then | |
saved, err = pcall(function() | |
DataManager.PData:UpdateAsync(player.Name.."-id",function(oldData) | |
return save | |
end) | |
end) | |
else | |
saved, err = pcall(function() | |
DataManager.PData:SetAsync(player.Name.."-id",save) | |
end) | |
end | |
if not err then | |
return true | |
else | |
print(err) | |
return false | |
end | |
end) | |
if success then | |
print("Data saved for ".. player.Name .. " successfully.") | |
end | |
return success | |
end | |
function DataManager:LoadDeploymentMode(player) | |
local result = "Ground" | |
local data = DataManager.PData:GetAsync(player.Name.."-id") | |
if data then | |
result = data.DeploymentMode | |
end | |
return result | |
end | |
function DataManager:GetSavedInventoryMode(player) | |
local result = "Loadout" | |
local data = DataManager.PData:GetAsync(player.Name.."-id") | |
if data then | |
result = data.i8Mode | |
end | |
return result | |
end | |
function DataManager:UpdateCredits(plr,amount) | |
RemoteService.send("Client",plr,"UpdateCurrency",amount) | |
end | |
game.Players.PlayerAdded:connect(function(plr) | |
if game.Players.NumPlayers == 1 then | |
RemoteService = GetMod(game.ReplicatedStorage.RemoteService) | |
RemoteService.listen("Server","Send","UnlockArmor",function(plr,armorName) | |
if not plr.UnlockedArmor:FindFirstChild("Unlocked"..armorName).Value then | |
plr.UnlockedArmor:FindFirstChild("Unlocked"..armorName).Value = true | |
end | |
end) | |
end | |
end) | |
function DataManager:GetFirstMarketplaceData() | |
return { | |
LastLoginReward = 0; | |
} | |
end | |
function DataManager:GetStarterSettings() | |
local settings = { | |
} | |
return settings | |
end | |
function DataManager:GrantDailyReward(player) | |
local success = DataManager:TryTransaction(function() | |
MarketService:CheckDailyLogin(player,DataManager.MarketplaceData) | |
end) | |
return success | |
end | |
function DataManager:GetSavedAchievements(player) | |
local data = DataManager.PData:GetAsync(player.Name .. "-id") | |
local result = {} | |
if data then | |
result = data.Achievements | |
end | |
return result | |
end | |
function DataManager:GetSavedTraits(player) | |
local result = {} | |
local data = DataManager.PData:GetAsync(player.Name .. "=id") | |
if data then | |
result = data.Traits | |
end | |
return result | |
end | |
function DataManager:GetLoadoutDefault(player,slot) | |
return LoadoutDefaults[player.Team.Name][slot] | |
end | |
function DataManager:GetFirstLoadSaveGame(Starting) | |
local save = { | |
Lvl = 1, | |
XP = 0, | |
Credits = Starting.StartingCurrency, | |
Attributes = { | |
Strength = Starting.StartingAttributes, | |
Intelligence = Starting.StartingAttributes, | |
Dexterity = Starting.StartingAttributes, | |
Constitution = Starting.StartingAttributes, | |
Charisma = Starting.StartingAttributes, | |
}, | |
AttributePoints = RPGM:GetStartingAttributePoints(1), | |
PVPScore = 0, | |
InPvP = false, | |
Team = "Jedi", | |
CA = { | |
HairColor = "Really red", | |
SkinColor = "Really blue", | |
PantsTemplate = "rbxassetid://318333315", | |
ShirtTemplate = "rbxassetid://318333010" | |
}, | |
CharacterName = "Null", | |
Armor = {}; | |
AlreadyCustomized = false; | |
ForceColor = nil; | |
KDR = { | |
Kills = 0; | |
}; | |
Squad = { | |
}; | |
i8Mode = "Loadout"; | |
Achievements = { | |
}; | |
Loadout = { | |
Name = "Main"; | |
}; | |
Traits = { | |
}; | |
DeploymentMode = "Ground"; | |
} | |
save.EquippedArmor = { | |
hasArmorOn = false; | |
ArmorType = "None"; | |
CurrentPlacement = "None"; | |
} | |
save.Camos = { | |
} | |
for _,Armor in pairs(AvailableArmor) do | |
save.Armor["Unlocked"..Armor] = false | |
end | |
for name,value in pairs(LoadoutDefaults["Jedi"]) do | |
save.Loadout[name] = value | |
end | |
return save | |
end | |
function DataManager:GetRandomForceColor(player) | |
local TeamName = player.Team.Name | |
local SaberColors = require(game.Teams:FindFirstChild(TeamName).SaberColors) | |
local SaberColor = SaberColors[RANDOM(1,#SaberColors)] | |
return SaberColor | |
end | |
function DataManager:SetLoadoutForSaving(player,Loadout) | |
PlayerLoadouts[player.UserId] = Loadout | |
end | |
function DataManager:CreateMainStats(player,score1,PVP) | |
local stats = OBJ("Model") | |
stats.Name = "leaderstats" | |
stats.Parent = player | |
local clicks = OBJ("IntValue") | |
clicks.Name = "Lvl" | |
clicks.Value = score1.Lvl | |
clicks.Parent = stats | |
local clicks2 = OBJ("IntValue") | |
clicks2.Name = "XP" | |
clicks2.Value = score1.XP | |
clicks2.Parent = stats | |
CurrentXP[player.UserId] = clicks2.Value | |
local clicks3 = OBJ("IntValue") | |
clicks3.Name = "Credits" | |
clicks3.Value = score1.Credits | |
clicks3.Parent = stats | |
if PVP.HasPvP == true then | |
local clicksPvP = Instance.new("IntValue") | |
clicksPvP.Name = "PVPRank" | |
clicksPvP.Value = score1.PVPScore or 0 | |
clicksPvP.Parent = stats | |
end | |
return stats | |
end | |
function DataManager:CreateAttributes(player,score1,level) | |
local attrb = OBJ("Model") | |
attrb.Name = "attributes" | |
attrb.Parent = player | |
local attrb1 = OBJ("IntValue") | |
attrb1.Name = "Strength" | |
attrb1.Value = score1.Attributes.Strength | |
attrb1.Parent = attrb | |
local attrb2 = OBJ("IntValue") | |
attrb2.Name = "Constitution" | |
attrb2.Value = score1.Attributes.Constitution | |
attrb2.Parent = attrb | |
local attrb3 = OBJ("IntValue") | |
attrb3.Name = "Intelligence" | |
attrb3.Value = score1.Attributes.Intelligence | |
attrb3.Parent = attrb | |
local attrb4 = OBJ("IntValue") | |
attrb4.Name = "Dexterity" | |
attrb4.Value = score1.Attributes.Dexterity | |
attrb4.Parent = attrb | |
local attrb6 = OBJ("IntValue") | |
attrb6.Name = "Charisma" | |
attrb6.Value = score1.Attributes.Charisma | |
attrb6.Parent = attrb | |
local attrb5 = OBJ("IntValue") | |
attrb5.Name = "APs" | |
attrb5.Value = score1.AttributePoints | |
attrb5.Parent = attrb | |
return attrb | |
end | |
function DataManager:CreateSecondaryStats(player,score1,level,Intelligence) | |
local misc = OBJ("Model") | |
misc.Name = "Stats" | |
misc.Parent = player | |
local inPvP = OBJ("BoolValue") | |
inPvP.Name = "InPvP" | |
inPvP.Value = score1.InPvP or false | |
inPvP.Parent = misc | |
local mana = OBJ("IntValue") | |
mana.Name = "Mana" | |
mana.Value = 100 | |
mana.Parent = misc | |
local maxmana = OBJ("IntValue") | |
maxmana.Name = "MaxMana" | |
maxmana.Value = RPGM.Mana(level,Intelligence) | |
maxmana.Parent = misc | |
local class2 = OBJ("StringValue") | |
class2.Name = "FactionClass" | |
class2.Value = score1.Team | |
class2.Parent = misc | |
local maxstamina = OBJ("IntValue") | |
maxstamina.Name = "MaxStamina" | |
maxstamina.Value = RPGM.MaxStamina(player) | |
maxstamina.Parent = misc | |
local stamina = OBJ("IntValue") | |
stamina.Name = "Stamina" | |
stamina.Value = maxstamina.Value | |
stamina.Parent = misc | |
local defense = OBJ("IntValue") | |
defense.Name = "Defense" | |
defense.Value = 0 | |
defense.Parent = misc | |
return misc | |
end | |
function DataManager:GetSettings(player) | |
local result = DataManager:GetStarterSettings() | |
local data = DataManager.Settings:GetAsync(player.UserId) | |
if data then | |
result = data | |
end | |
return result | |
end | |
function DataManager:CreateSoldierStats(player,SoldierObj) | |
local UnitAttrs = UnitData[player.Allegiance.Value][SoldierObj.Type].Attributes | |
Squads[player.UserId][#Squads[player.UserId]+1] = Soldier.new(SoldierObj.Type,SoldierObj.Helmet,SoldierObj.Weapon,UnitAttrs.Dexterity,UnitAttrs.Strength,UnitAttrs.Intelligence,UnitAttrs.Constitution,UnitAttrs.Charisma) | |
return Squads[player.UserId][#Squads[player.UserId]] | |
end | |
function DataManager:SaveHighScore(player,scoreType) | |
local score | |
if scoreType == "XP" then | |
score = RPGM.TotalXP(player.leaderstats.XP.Value,player.leaderstats.Lvl.Value) | |
elseif scoreType == "SquadPoints" then | |
score = 0 | |
elseif scoreType == "Credits" then | |
score = player.leaderstats.Credits.Value | |
end | |
local scoreTbl = {} | |
scoreTbl[scoreType] = score | |
DataManager.HighScores:SetAsync(player.UserId .. "-" ..scoreType,scoreTbl[scoreType]) | |
end | |
function DataManager:LoadHighScores(scoreType,threshold) | |
local pages = DataManager.HighScores:GetSortedAsync(false,threshold) | |
local names = {} | |
local scores = {} | |
local page = pages:GetCurrentPage() | |
for k, v in pairs(page) do | |
if string.match(v.key,"%a+") == scoreType then | |
names[k] = game.Players:GetNameFromUserIdAsync(tonumber(string.match(v.key,"%d+"))) | |
scores[k] = v.Value | |
end | |
end | |
return names, scores | |
end | |
function DataManager:CreateArmorData(player,score1) | |
local armor = OBJ("Folder") | |
armor.Name = "UnlockedArmor" | |
armor.Parent = player | |
for armorName,armorValue in pairs(score1.Armor) do | |
if armorName:find("Unlocked") then | |
local armorTag = OBJ("BoolValue") | |
armorTag.Name = armorName | |
armorTag.Value = armorValue | |
armorTag.Parent = armor | |
end | |
end | |
return armor | |
end | |
function DataManager:CreateEquipmentData(player,score1) | |
local equippedArmor = EquipmentInventory.new( | |
score1.EquippedArmor.hasArmorOn, | |
score1.EquippedArmor.ArmorType, | |
score1.EquippedArmor.CurrentPlacement, | |
ArmorSlots | |
); | |
return equippedArmor | |
end | |
function DataManager:UnloadKDR(player) | |
player.MissionStats.TotalKills.Value = player.MissionStats.TotalKills.Value + player.MissionStats.Kills.Value | |
player.MissionStats.Kills.Value = 0 | |
end | |
function DataManager:GetSavedData(player,Starting) | |
local data = DataManager:GetFirstLoadSaveGame(Starting) | |
local data2 = DataManager:GetFirstMarketplaceData() | |
if game:GetService("RunService"):IsStudio() then return data, data2 end | |
local success, tempData = DataManager:TryTransaction(function() | |
return DataManager.PData:GetAsync(player.Name.."-id") | |
end) | |
local success2, tempData2 = DataManager:TryTransaction(function() | |
return DataManager.MarketplaceData:GetAsync(player.UserId) | |
end) | |
if tempData then | |
data = tempData | |
end | |
if tempData2 then | |
data2 = tempData2 | |
end | |
return data, data2 | |
end | |
function DataManager:ResetForcePowers(player) | |
ForceLib:ResetForcePowers(player) | |
local ForceIndex = ForceLib:LoadForceTable(player) or {} | |
print(ForceIndex) | |
local StartingOut = false | |
if #ForceIndex == 0 then | |
StartingOut = true | |
for name, power in pairs(ForcePowers) do | |
local forcePowerObj = {} | |
if power then | |
forcePowerObj.Name = ((power.Label) and name or ("Force" .. name)) | |
forcePowerObj.FriendlyName = ((power.Label) and power.Label or ("Force " .. name)) | |
forcePowerObj.ManaCost = power.ManaCost | |
forcePowerObj.hasPower = power.defaultPower | |
forcePowerObj.Level = 1; | |
end | |
if forcePowerObj ~= {} then | |
ForceLib.SavePower(player,ForceLib.CreatePowerData(forcePowerObj),ForceIndex) | |
end | |
end | |
ForceLib:SaveForceData(player,ForceIndex) | |
end | |
end | |
function DataManager:LoadForceStats(player,score1,powersCache) | |
local ForceIndex = ForceLib:LoadForceTable(player) or {} | |
print(ForceIndex) | |
local StartingOut = false | |
if #ForceIndex == 0 then | |
StartingOut = true | |
for name, power in pairs(ForcePowers) do | |
local forcePowerObj = {} | |
if power then | |
forcePowerObj.Name = ((power.Label) and name or ("Force" .. name)) | |
forcePowerObj.FriendlyName = ((power.Label) and power.Label or ("Force " .. name)) | |
forcePowerObj.ManaCost = power.ManaCost | |
forcePowerObj.hasPower = power.defaultPower | |
forcePowerObj.Level = 1; | |
end | |
if forcePowerObj ~= {} then | |
ForceLib.SavePower(player,ForceLib.CreatePowerData(forcePowerObj),ForceIndex) | |
end | |
end | |
ForceLib:SaveForceData(player,ForceIndex) | |
end | |
powersCache[player.UserId] = {} | |
for i = 1,#ForceIndex do | |
local power = ForceLib:DecodePower(player,ForceIndex[i]) | |
powersCache[player.UserId][power.Name] = power | |
end | |
local ForceColor = OBJ("BrickColorValue") | |
ForceColor.Name = "ForceColor" | |
ForceColor.Value = score1.ForceColor ~= nil and BC(score1.ForceColor) or DataManager:GetRandomForceColor(player) | |
ForceColor.Parent = player | |
return { | |
["Color"] = ForceColor; | |
} | |
end | |
function DataManager:LoadSquad(player) | |
local data = DataManager.PData:GetAsync(player.Name .. "-id") | |
if data then | |
for _, squadmate in pairs(data.Squad) do | |
Squads[player.UserId][#Squads[player.UserId] + 1] = Soldier.FromReplicatedSquadmate(squadmate) | |
end | |
end | |
end | |
function DataManager:ResetPlayer(player,Starting) | |
local data = DataManager:GetFirstLoadSaveGame(Starting) | |
local success, err = DataManager:TryTransaction(function() | |
DataManager.PData:UpdateAsync(player.Name.."-id",function(oldData) | |
return data | |
end) | |
end) | |
end | |
DataManager.LZSpawns = { | |
["Good"] = { | |
CF(316.01, -134.287, -405.26); | |
CF(-574.19, -124.178, -1048.49); | |
CF(1439.136, -99.242, -1086.094); | |
}; | |
["Evil"] = { | |
CF(-1333.774, -118.057, -1265.183); | |
CF(-437.484, -118.057, -916.193); | |
CF(988.376, 40.568, -1299.074); | |
CF(988.376, 40.568, -1131.734); | |
} | |
} | |
function DataManager:LoadClassData(player,score1) | |
player.Team = game.Teams:FindFirstChild(score1.Team) or game.Teams["Jedi"] | |
local Allegiance = OBJ("StringValue") | |
Allegiance.Name = "Allegiance" | |
Allegiance.Value = ((player.Team.Name == "Bounty Hunters" or player.Team.Name == "Imperials") and "Evil" or "Good") | |
Allegiance.Parent = player | |
player.Changed:connect(function(prop) | |
if prop == "Team" then | |
Allegiance.Value = ((player.Team.Name == "Bounty Hunters" or player.Team.Name == "Imperials") and "Evil" or "Good") | |
end | |
end) | |
return Allegiance | |
end | |
function DataManager:GetSavedLoadout(player) | |
local result = LoadoutDefaults[player.Team.Name] | |
local data = DataManager.PData:GetAsync(player.Name .. "-id") | |
if data then | |
result = data.Loadout | |
end | |
return result | |
end | |
function DataManager:GetSlot(index) | |
return Slots:FindFirstChild("Stage"..index) | |
end | |
function DataManager:GetClassLoadout(class) | |
local ld = LoadoutDefaults[class] | |
if ld then | |
ld.Name = "Main" | |
end | |
return ld | |
end | |
function DataManager:HasNoTroops(playerArmy) | |
local result = false | |
local count = 0 | |
for _, soldier in pairs(playerArmy:GetChildren()) do | |
if soldier:FindFirstChild("Human") then | |
count = count + 1 | |
end | |
end | |
return count <= 0 | |
end | |
function DataManager:loadScores(player,Starting,Others,AttributeEffect,PerLevel,Caps,PVP,powersCache) | |
local score1,score3 = DataManager:GetSavedData(player,Starting) | |
Settings[player.UserId] = SetttingsCache.new(DataManager:GetSettings(player)) | |
local AlreadyCustomized = OBJ("BoolValue") | |
AlreadyCustomized.Name = "AlreadyCustomized" | |
AlreadyCustomized.Value = score1.AlreadyCustomized | |
AlreadyCustomized.Parent = player | |
Squads[player.UserId] = {} | |
PlayerLoadouts[player.UserId] = {} | |
local Allegiance = DataManager:LoadClassData(player,score1) | |
local stats = DataManager:CreateMainStats(player,score1,PVP) | |
local attrb = DataManager:CreateAttributes(player,score1,stats.Lvl) | |
local secStats = DataManager:CreateSecondaryStats(player,score1,stats.Lvl,attrb.Intelligence) | |
local armor = DataManager:CreateArmorData(player,score1) | |
local equippedArmor = DataManager:CreateEquipmentData(player,score1) | |
EquipmentCache[player.UserId] = equippedArmor | |
local ForceData = DataManager:LoadForceStats(player,score1,powersCache) | |
player:WaitForChild("Inventory",200).ChildAdded:connect(function(item) | |
if item:IsA("Tool") then | |
if not item:FindFirstChild("ID") then | |
local Id = TSS:MakeID(item) | |
end | |
end | |
end) | |
DataManager:LoadSquad(player) | |
local CurrentTutorialMatch = Instance.new("StringValue") | |
CurrentTutorialMatch.Name = "CurrentTutorialMatch" | |
CurrentTutorialMatch.Value = "" | |
CurrentTutorialMatch.Parent = player | |
local cn = OBJ("StringValue") | |
cn.Name = "CharacterName" | |
cn.Value = score1.CharacterName | |
cn.Parent = player | |
DataManager:GrantDailyReward(player) | |
local Slot = OBJ("ObjectValue") | |
Slot.Name = "CustomizationSlot" | |
Slot.Parent = player | |
if not AlreadyCustomized.Value then | |
Slot.Value = DataManager:GetSlot(DataManager:NumPlayersUnCustomized()) | |
end | |
local MissionStats = OBJ("Folder") | |
MissionStats.Name = "MissionStats" | |
MissionStats.Parent = player | |
local Kills = OBJ("IntValue") | |
Kills.Name = "Kills" | |
Kills.Value = 0 | |
Kills.Parent = MissionStats | |
local TKills = OBJ("IntValue") | |
TKills.Name = "TotalKills" | |
TKills.Value = 0 | |
TKills.Parent = MissionStats | |
local playerArmy = nil | |
local CAD = OBJ("Folder",player) | |
CAD.Name = "CharacterAppearanceData" | |
local HairColor = OBJ("StringValue",CAD) | |
HairColor.Name = "HairColor" | |
HairColor.Value = score1.CA.HairColor | |
local SkinColor = OBJ("StringValue",CAD) | |
SkinColor.Name = "SkinColor" | |
SkinColor.Value = score1.CA.SkinColor | |
local ShirtTemplate = OBJ("StringValue",CAD) | |
ShirtTemplate.Name = "ShirtTemplate" | |
ShirtTemplate.Value = score1.CA.ShirtTemplate | |
local PantsTemplate = OBJ("StringValue",CAD) | |
PantsTemplate.Name = "PantsTemplate" | |
PantsTemplate.Value = score1.CA.PantsTemplate | |
PlayerSquads[player.UserId] = SquadClass.new(player,{}) | |
local playerArmy = PlayerSquads[player.UserId]:GetContainer() | |
local playerArmyBackpackRoot = Instance.new("Folder") | |
playerArmyBackpackRoot.Name = playerArmy.Name .."_BackpackRoot" | |
playerArmyBackpackRoot.Parent = game.ReplicatedStorage.MobBackpack | |
local pABRT = playerArmy:FindFirstChild("playerArmyBackpackRoot") or Instance.new("ObjectValue") | |
pABRT.Name = "playerArmyBackpackRoot" | |
pABRT.Value = playerArmyBackpackRoot | |
pABRT.Parent = playerArmy | |
local MSpeaker = playerArmy:FindFirstChild("MobSpeaker") or script.MobSpeaker:Clone() | |
MSpeaker.Parent = playerArmy | |
local pAT = player:FindFirstChild("playerArmy") or Instance.new("ObjectValue") | |
pAT.Name = "playerArmy" | |
pAT.Value = playerArmy | |
pAT.Parent = player | |
local SoldierTransferPoint | |
SoldierTransferPoint = player:FindFirstChild("Soldier_"..player.Name) or Instance.new("Folder") | |
SoldierTransferPoint.Name = "Soldier_"..player.Name | |
SoldierTransferPoint.Parent = player | |
stats.XP.Changed:connect(function() DataManager:UpgradePlayerByXP(Others,PerLevel,Caps,player,Starting, stats.XP, stats.Lvl) end) | |
stats.Lvl.Changed:connect(function(value) DataManager:UpgradePlayerByLevel(player, stats.XP, stats.Lvl) end) | |
stats.Credits.Changed:connect(function(value) | |
DataManager:UpdateCredits(player,value) | |
end) | |
player.CharacterAdded:connect(function(c) | |
spawn(function() | |
for _, soldier in pairs(playerArmy:GetChildren()) do | |
if soldier:FindFirstChild("Human") or soldier.Name == "SpawnCraft" then | |
soldier:Destroy() | |
end | |
end | |
if DataManager:HasNoTroops(playerArmy) then | |
local ArmyReady = false | |
if player.DeploymentMode.Value == "Transport" then | |
local SpawnCraft = game.ReplicatedStorage.AirSupport:FindFirstChild(player.Allegiance.Value).SpawnCraft:Clone() | |
local CraftSpawns = workspace.AirSpawns:GetChildren() | |
local CS = CraftSpawns[RANDOM(1,#CraftSpawns)] | |
SpawnCraft:SetPrimaryPartCFrame(CS.CFrame + Vector3.new(0,SpawnCraft.PrimaryPart.Size.Y,0)) | |
SpawnCraft.PrimaryPart.Owner.Value = player | |
local spawns = DataManager.LZSpawns[player.Allegiance.Value] | |
local LZSpawn = spawns[RANDOM(1,#spawns)] | |
-- if LZSpawn.Parent.TutorialTag.Value then | |
-- if (TutorialService.IsInNeedOfATutorial(player,LZSpawn.Parent.TutorialTag.Value)) then | |
-- local TutorialTag = TutorialService.MakeTutorialTag(player,LZSpawn.Parent.TutorialTag.Value) | |
-- end | |
-- end | |
SpawnCraft:SetPrimaryPartCFrame(CF(SpawnCraft.PrimaryPart.Position,SpawnCraft.PrimaryPart.Position + ((CS.FacePart.CFrame.p - SpawnCraft.PrimaryPart.Position).unit * V3(1,0,1))) * CFrame.Angles(0,math.rad(180),0)) | |
local Spawns = SpawnCraft.Bodykit.TroopPlacement:GetChildren() | |
SpawnCraft.Parent = playerArmy | |
SpawnCraft.PrimaryPart.Anchored = true | |
ArmyReady = true | |
for i = 1,#Squads[player.UserId] do | |
spawn(function() | |
local Soldier = game.ReplicatedStorage.SquadUnitStorage:FindFirstChild(player.Allegiance.Value).Soldier:Clone() | |
Soldier.Leader.Value = player | |
Soldier.UnitName.Value = "Unit "..i | |
local IDVal = Instance.new("IntValue") | |
IDVal.Name = "ID" | |
IDVal.Value = i | |
IDVal.Parent = Soldier | |
Soldier.Pants.PantsTemplate = UnitData[player.Allegiance.Value][Squads[player.UserId][i].Type].Clothes.Pants | |
Soldier.Shirt.ShirtTemplate = UnitData[player.Allegiance.Value][Squads[player.UserId][i].Type].Clothes.Shirt | |
local UnitBackpack = script.SoldierPack:Clone() | |
UnitBackpack.Name = "Unit"..i.."Backpack" | |
UnitBackpack.Parent = pABRT.Value | |
Soldier.Backpack.Value = UnitBackpack | |
PlayerSquads[player.UserId]:AddMember(Soldier) | |
Soldier.Parent = playerArmy | |
local si = i | |
local spawnPart = Spawns[si].SkateboardPlatform | |
repeat | |
Soldier.Torso.CFrame = spawnPart.CFrame + Vector3.new(0,2,0) | |
wait() | |
until Soldier.Human.PlatformStand | |
end) | |
wait(0.2) | |
end | |
repeat wait() until SpawnCraft.Welded.Value | |
repeat | |
local si = #Squads[player.UserId] + 1 | |
local spawnPart = Spawns[si].SkateboardPlatform | |
c.Torso.CFrame = spawnPart.CFrame + Vector3.new(0,1,0) game:GetService("RunService").Heartbeat:wait() | |
until c.Humanoid.PlatformStand | |
local TController = require(SpawnCraft.TransportController) | |
TController:EnableAutoPilot() | |
TController:StartEngine(false) | |
spawn(function() | |
SpawnCraft.PrimaryPart.Anchored = false | |
c.LZCam.InUse.Value = true | |
TController:TravelWithAutoPilot(LZSpawn.p,function() | |
BindableService.send("EquipLoadout",player) | |
PlayerSquads[player.UserId]:ListenServer() | |
PlayerSquads[player.UserId]:Listen() | |
TController:ReleasePassengers() | |
wait(10) | |
TController:Takeoff(true) | |
TController = nil | |
end) | |
end) | |
else | |
local spawns = workspace.SquadSpawns:GetChildren() | |
local spawnPos = spawns[RANDOM(#spawns)] | |
local SpawnCF = spawnPos.CFrame | |
c.Torso.CFrame = SpawnCF + V3(0,3,0) | |
for i = 1,#Squads[player.UserId] do | |
spawn(function() | |
local Soldier = game.ReplicatedStorage.SquadUnitStorage:FindFirstChild(player.Allegiance.Value).Soldier:Clone() | |
Soldier.Leader.Value = player | |
Soldier.UnitName.Value = "Unit "..i | |
local IDVal = Instance.new("IntValue") | |
IDVal.Name = "ID" | |
IDVal.Value = i | |
IDVal.Parent = Soldier | |
Soldier.Pants.PantsTemplate = UnitData[player.Allegiance.Value][Squads[player.UserId][i].Type].Clothes.Pants | |
Soldier.Shirt.ShirtTemplate = UnitData[player.Allegiance.Value][Squads[player.UserId][i].Type].Clothes.Shirt | |
local UnitBackpack = script.SoldierPack:Clone() | |
UnitBackpack.Name = "Unit"..i.."Backpack" | |
UnitBackpack.Parent = pABRT.Value | |
Soldier.Backpack.Value = UnitBackpack | |
PlayerSquads[player.UserId]:AddMember(Soldier) | |
Soldier.Parent = playerArmy | |
Soldier.Torso.CFrame =c.Torso.CFrame + V3(0,0,-IDVal.Value) | |
end) | |
wait(0.2) | |
end | |
BindableService.send("EquipLoadout",player) | |
PlayerSquads[player.UserId]:Listen() | |
PlayerSquads[player.UserId]:ListenServer() | |
end | |
end | |
end) | |
DataManager:ConvertToCharacterAppearance(score1.CA,player,c,CAD) | |
DataManager:UpdateCredits(player,stats.Credits.Value) | |
if Starting.DefenseMode == 3 then | |
if secStats:FindFirstChild("Defense") then | |
c.Humanoid.MaxHealth = RPGM.MaxHPWithDefense(stats.Lvl,attrb.Constitution,secStats.Defense) | |
else | |
c.Humanoid.MaxHealth = RPGM.MaxHP(player.leaderstats.Lvl,player.attributes.Constitution) | |
end | |
else | |
c.Humanoid.MaxHealth = RPGM.MaxHP(player.leaderstats.Lvl,player.attributes.Constitution) | |
end | |
secStats.MaxMana.Value = RPGM.Mana(stats.Lvl,attrb.Intelligence) | |
c.Humanoid.Health = c.Humanoid.MaxHealth | |
secStats.Mana.Value = secStats.MaxMana.Value | |
secStats.MaxStamina.Value = RPGM.MaxStamina(player) | |
secStats.Stamina.Value = secStats.MaxStamina.Value | |
c:WaitForChild("Health",200):Destroy() | |
end) | |
end | |
RemoteService.listen("Server","Fetch","CreateSoldier",function(player,SoldierObj) | |
return DataManager:CreateSoldierStats(player,SoldierObj) | |
end) | |
RemoteService.listen("Server","Send","EraseSoldierStats",function(player) | |
Squads[player.UserId] = {} | |
end) | |
function DataManager:UpdateCurrentEquipmentPlacement(player,placement,value) | |
EquipmentCache[player.UserId].Placement[placement].Armor = value | |
end | |
function DataManager:ToggleCurrentEpuipmentPlacement(player,placement,on) | |
EquipmentCache[player.UserId].Placement[placement].On = on | |
end | |
function DataManager:SetCurrentPlacement(player,value) | |
EquipmentCache[player.UserId].CurrentPlacement = value | |
end | |
function DataManager:GetArmorWithPlacement(player,placement) | |
return EquipmentCache[player.UserId][placement].Armor | |
end | |
function DataManager:GetCurrentPlacement(player) | |
return EquipmentCache[player.UserId].CurrentPlacement | |
end | |
function DataManager:IsEquipmentReady(player) | |
return EquipmentCache[player.UserId] | |
end | |
function DataManager:GetSquadWeapon(player,id) | |
return Squads[player.UserId][id]:GetWeapon() | |
end | |
function DataManager:GetSquadHelmet(player,id) | |
return Squads[player.UserId][id].Helmet | |
end | |
function DataManager:GetSquadAttributes(player,id) | |
return Squads[player.UserId][id].Attributes | |
end | |
function DataManager:CreateHBar(player,id,squadMember) | |
Squads[player.UserId][id]:CreateHealthBar(squadMember) | |
end | |
function DataManager:UpdateAttributes(player,id,attr,amt) | |
Squads[player.UserId][id]:IncreaseAttributes(attr,amt) | |
end | |
RemoteService.listen("Server","Send","SetCEPlacment",function(player,placement,value) | |
DataManager:UpdateCurrentEquipmentPlacement(player,placement,value) | |
end) | |
RemoteService.listen("Server","Send","SetCEPlacmentOn",function(player,placement,on) | |
DataManager:ToggleCurrentEpuipmentPlacement(player,placement,on) | |
end) | |
RemoteService.listen("Server","Fetch","GetPlayerArmyLocation",function(player) | |
return PlayerSquads[player.UserId]:GetContainer() | |
end) | |
return DataManager |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local KillService = {} | |
local QuestService = require(script.Parent.QuestService) | |
KillService.Kills = {} | |
KillService.AllKills = {} | |
KillService.TotalKills = {} | |
KillService.WaveKills = {} | |
local RemoteService = require(game.ReplicatedStorage.RemoteService) | |
local BindingService = require(game.ReplicatedStorage.BindingService)() | |
local SignalAPI = require(game.ReplicatedStorage.SignalAPI) | |
KillService.KillAdded = SignalAPI.Create() | |
KillService.StreakTypes = { | |
[2] = { | |
Name = "2kill"; | |
}; | |
[3] = { | |
Name = "3kill"; | |
}; | |
[4] = { | |
Name = "4kill"; | |
}; | |
[5] = { | |
Name = "5kill"; | |
}; | |
[6] = { | |
Name = "6kill"; | |
} | |
} | |
KillService.Achievements = { | |
{ | |
Kills = 5; | |
ID = 4; | |
}; | |
{ | |
Kills = 10; | |
ID = 5; | |
}; | |
{ | |
Kills = 25; | |
ID = 6; | |
}; | |
{ | |
Kills = 50; | |
ID = 7; | |
}; | |
{ | |
Kills = 100; | |
ID = 8; | |
}; | |
{ | |
Kills = 250; | |
ID = 9; | |
}; | |
{ | |
Kills = 500; | |
ID = 10; | |
}; | |
{ | |
Kills = 750; | |
ID = 11; | |
}; | |
{ | |
Kills = 1000; | |
ID = 12; | |
}; | |
{ | |
Kills = 1250; | |
ID = 13; | |
}; | |
{ | |
Kills = 1500; | |
ID = 14; | |
}; | |
{ | |
Kills = 2000; | |
ID = 15; | |
} | |
} | |
KillService.Kill = require(script.Kill) | |
function KillService:RegisterPlayer(plr,count) | |
KillService.Kills[plr.UserId] = {} | |
KillService.AllKills[plr.UserId] = {} | |
KillService.TotalKills[plr.UserId] = count or 0 | |
KillService.WaveKills[plr.UserId] = 0 | |
plr:WaitForChild("leaderstats",200) | |
KillService.AllKills[plr.UserId][plr.leaderstats.Lvl.Value] = {} | |
spawn(function() | |
plr.leaderstats.Lvl.Changed:connect(function(level) | |
KillService.AllKills[plr.UserId][level] = {} | |
end) | |
end) | |
end | |
function KillService:AddKill(...) | |
local args = {...} | |
local kill = KillService.Kill.new(...) | |
KillService.KillAdded:fire(args[2],kill) | |
script.KillAdded:Fire(kill) | |
KillService.Kills[args[2].UserId][#KillService.Kills[args[2].UserId]+1] = kill | |
KillService.TotalKills[args[2].UserId] = KillService.TotalKills[args[2].UserId] + 1 | |
if QuestService:HasQuest(args[2],"WaveDilemma_" .. args[2].Allegiance.Value) then KillService.WaveKills[args[2].UserId] = KillService.WaveKills[args[2].UserId] + 1 end | |
if KillService:GetStreakCount(args[2]) > 1 and ((KillService.Kills[args[2].UserId][#KillService.Kills[args[2].UserId]]) - (KillService.Kills[args[2].UserId][#KillService.Kills[args[2].UserId] - 1]) >= 10) then | |
KillService:ClearKills(args[2]) | |
else | |
if KillService:GetStreakCount(args[2]) > 1 then | |
if KillService:GetStreakCount(args[2]) < 6 then | |
RemoteService.send("Client",args[2],"DisplayAward",5,KillService.StreakTypes[#KillService.Kills[args[2].UserId]].Name) | |
args[2].leaderstats.XP.Value = args[2].leaderstats.XP.Value + 5 | |
else | |
RemoteService.send("Client",args[2],"DisplayAward",5,KillService.StreakTypes[6].Name) | |
args[2].leaderstats.XP.Value = args[2].leaderstats.XP.Value + 5 | |
end | |
end | |
end | |
print(KillService:GetStreakCount(args[2])) | |
KillService.AllKills[args[2].UserId][args[2].leaderstats.Lvl.Value][#KillService.AllKills[args[2].UserId][args[2].leaderstats.Lvl.Value]+1] = KillService.Kills[args[2].UserId][#KillService.Kills[args[2].UserId]+1] | |
for _, AchievementMan in pairs(KillService.Achievements) do | |
if AchievementMan then | |
if KillService:GetTotalKills(args[2]) == AchievementMan.Kills then | |
BindingService.send("GiveAchievement",args[2],AchievementMan.ID) | |
end | |
end | |
end | |
end | |
function KillService:ClearKills(plr) | |
KillService.Kills[plr.UserId] = {} | |
end | |
function KillService:GetStreakCount(plr) | |
return #KillService.Kills[plr.UserId] | |
end | |
function KillService:GetTotalKills(plr) | |
return KillService.TotalKills[plr.UserId] | |
end | |
return KillService |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Objective = {} | |
Objective.__index = Objective | |
function Objective.new(...) | |
local o = {} | |
local args = {...} | |
o.Name = args[1] | |
o.Text = args[2] | |
o.Completed = false | |
o.Parent = args[3] | |
o.XPGain = math.random(5,25); | |
o.Type = args[4] | |
if o.Type == "Custom" then | |
elseif o.Type == "Kill" then | |
o.Goal = args[5] | |
o.GoalCount = args[6] | |
o.CompletedGoalCount = 0; | |
end | |
return setmetatable(o,Objective) | |
end | |
function Objective:Complete(func) | |
self.Completed = true | |
func(self) | |
self = nil | |
end | |
function Objective:ToReplicatedObjective() | |
local o = {} | |
o.Name = self.Name | |
o.Text = self.Text | |
o.Type = self.Type | |
o.Completed = self.Completed | |
return o | |
end | |
return Objective |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local MobService = require(game.ServerScriptService.MobFunctions) | |
local Pathfinder = MobService.Pathfinder.new(script.Parent.HumanoidRootPart,script.Parent.Human,script.Parent) | |
--[[ | |
Basic Monster by ArceusInator | |
Information: | |
Configurations.MaximumDetectionDistance (default 200) | |
The monster will not detect players past this point. If you set it to a negative number then the monster will be able to chase from any distance. | |
Configurations.CanGiveUp (default true) | |
If true, the monster will give up if its target goes past the MaximumDetectionDistance. This is a pretty good idea if you have people teleporting around. | |
Configurations.CanRespawn (default true) | |
If true, the monster will respawn after it dies | |
Configurations.AutoDetectSpawnPoint (default true) | |
If true, the spawn point will be auto detected based on where the monster is when it starts | |
Configurations.SpawnPoint (default 0,0,0) | |
If Settings.AutoDetectSpawnPoint is disabled, this will be set to the monster's initial position. This value will be used when the monster auto respawns to tell it where to spawn next. | |
Configurations.FriendlyTeam (default Really black) | |
The monster will not attack players on this team | |
Mind.CurrentTargetHumanoid (Humanoid objects only) | |
You can force the monster to follow a certain humanoid by setting this to that humanoid | |
Monster.Respawn (Function) | |
Arguments are: Vector3 point | |
Info: Respawns the monster at the given point, or at the SpawnPoint setting if none if provided | |
Monster.Died (Event) | |
Info: Fired when the monster dies | |
Monster.Respawned (Event) | |
Info: Fired when the monster respawns | |
--]] | |
local Self = script.Parent | |
local Mind = Self:FindFirstChild'Mind' -- Points to the monster's mind. You can edit parts of this from other scripts in-game to change the monster's behavior. Advanced users only. | |
local OrderList = Self:FindFirstChild'OrderQueue' | |
local BOTBrain = require(Self:FindFirstChild('BOT')) | |
Self.CurrentItem.Changed:wait() | |
local Weapon = Self.CurrentItem.Value | |
local wSettings = require(Weapon.SETTINGS) | |
local CF = CFrame.new | |
local Target = nil | |
Self.CurrentItem.Changed:connect(function(item) | |
if item then | |
Weapon = item | |
wSettings = require(Weapon.SETTINGS) | |
end | |
end) | |
Self.SetTarget.Event:connect(function(target) | |
Target = target | |
end) | |
Self.GetTarget.OnInvoke = function() | |
return Target | |
end | |
-- Verify that everything is where it should be | |
function getEnemies(Parent) | |
local iEnemies = Parent:GetChildren() | |
local eEnemies = {} | |
for _, enemy in pairs(iEnemies) do | |
table.insert(eEnemies,enemy) | |
end | |
return eEnemies | |
end | |
local Info = { | |
-- These are constant values. Don't change them unless you know what you're doing. | |
-- Advanced settings | |
RecomputePathFrequency = 1, -- The monster will recompute its path this many times per second | |
RespawnWaitTime = 5, -- How long to wait before the monster respawns | |
JumpCheckFrequency = 1, -- How many times per second it will do a jump check | |
} | |
local Data = { | |
-- These are variable values used internally by the script. Advanced users only. | |
LastRecomputePath = 0, | |
Recomputing = false, -- Reocmputing occurs async, meaning this script will still run while it's happening. This variable will prevent the script from running two recomputes at once. | |
IsDead = false, | |
TimeOfDeath = 0, | |
CurrentNode = nil, | |
CurrentNodeIndex = 1, | |
AutoRecompute = true, | |
LastJumpCheck = 0, | |
LastAttack = 0, | |
} | |
-- | |
-- | |
local Monster = {} -- Create the monster class | |
function Monster:GetCFrame() | |
-- Returns the CFrame of the monster's humanoidrootpart | |
local humanoidRootPart = Self:FindFirstChild('HumanoidRootPart') | |
if humanoidRootPart ~= nil and humanoidRootPart:IsA('BasePart') then | |
return humanoidRootPart.CFrame | |
else | |
return CF() | |
end | |
end | |
function Monster:GetMaximumDetectionDistance() | |
-- Returns the maximum detection distance | |
local setting = BOTBrain.ChaseRange | |
if setting < 0 then | |
return math.huge | |
else | |
return setting | |
end | |
end | |
function Monster:HeadForCover() | |
Self.CustomMove.Value = true | |
local Cover = getCoverPoints() | |
local CoverPoint = Cover[math.random(#Cover)] | |
Pathfinder.Target = CoverPoint.CFrame.p | |
Pathfinder:ComputePath() | |
Pathfinder:Start(1,function() | |
end) | |
Pathfinder.Stopped:wait() | |
Data.InCover = true | |
Self.TakingCover.Value = true | |
Self.CoverPoint.Value = CoverPoint.Parent | |
end | |
function Monster:GetTargetCFrame() | |
local targetHumanoid = Target | |
if Monster:TargetIsValid() and targetHumanoid.Parent.PrimaryPart ~= nil then | |
return targetHumanoid.Parent.PrimaryPart.CFrame | |
else | |
return CF() | |
end | |
end | |
function Monster:IsAlive() | |
return Self.Human.Health > 0 and Self.Human.Torso ~= nil | |
end | |
function Monster:TargetIsValid() | |
local targetHumanoid = Target | |
if targetHumanoid ~= nil and targetHumanoid:IsA 'Humanoid' and (not targetHumanoid:IsDescendantOf(workspace.CorpseIgnore)) and targetHumanoid.Parent ~= nil then | |
return true | |
else | |
return false | |
end | |
end | |
function Monster:HasClearLineOfSight() | |
-- Going to cast a ray to see if I can just see my target | |
local myPos, targetPos = Monster:GetCFrame().p, Monster:GetTargetCFrame().p | |
local hit, pos = workspace:FindPartOnRayWithIgnoreList( | |
Ray.new( | |
myPos, | |
targetPos - myPos | |
), | |
{ | |
Self, | |
Self.CoverPoint.Value | |
} | |
) | |
if hit ~= nil and hit:IsDescendantOf(Mind.CurrentTargetHumanoid.Value.Parent) then | |
return true | |
else | |
return false | |
end | |
end | |
function Monster:HasClearLineOfSightFromPoint(point) | |
-- Going to cast a ray to see if I can just see my target | |
local myPos, targetPos = point.p, Monster:GetTargetCFrame().p | |
local hit, pos = workspace:FindPartOnRayWithIgnoreList( | |
Ray.new( | |
point.p, | |
point.lookVector | |
), | |
{ | |
Self, | |
Self.CoverPoint.Value.Parent | |
} | |
) | |
if hit ~= nil and hit:IsDescendantOf(Target.Parent) then | |
return true | |
else | |
return false | |
end | |
end | |
function Monster:Update() | |
end | |
function Monster:GetClosestEnemiesWithCount(count) | |
local bindableService = require(game.ReplicatedStorage.BindingService)() | |
local enemies = {} | |
for _, enemy in pairs(workspace.Mobs:GetChildren()) do | |
if enemy then | |
if enemy:FindFirstChildOfClass("Humanoid") then | |
if require(enemy.BOT).Allegiance ~= BOTBrain.Allegiance and enemy.PrimaryPart then | |
local distance = (enemy.PrimaryPart.CFrame.p - Self.PrimaryPart.CFrame.p).magnitude | |
if distance < BOTBrain.ChaseRange then | |
enemies[#enemies+1] = enemy | |
if #enemies >= count then | |
break | |
end | |
end | |
end | |
end | |
end | |
end | |
if #enemies < count then | |
for _, enemy in pairs(bindableService.fetch("PlayerList")) do | |
if enemy then | |
if enemy.Character then | |
if enemy.Character:FindFirstChildOfClass("Humanoid") then | |
if enemy.Allegiance.Value ~= BOTBrain.Allegiance then | |
local distance = (enemy.Character.PrimaryPart.CFrame.p - Self.PrimaryPart.CFrame.p).magnitude | |
if distance < BOTBrain.ChaseRange then | |
enemies[#enemies+1] = enemy.Character | |
for _, secondEnemy in pairs(enemy.playerArmy.Value:GetChildren()) do | |
if secondEnemy:FindFirstChildOfClass("Humanoid") and secondEnemy.PrimaryPart then | |
local distance = (secondEnemy.PrimaryPart.CFrame.p - Self.PrimaryPart.CFrame.p).magnitude | |
if distance < BOTBrain.ChaseRange then | |
enemies[#enemies+1] = secondEnemy | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
return enemies | |
end | |
function Monster:Talk(message) | |
Self.Parent.MobSpeaker.Speak:Fire(Self.UnitName.Value,message) | |
end | |
function Monster:Initialize() | |
end | |
function Monster:InitializeUnique() | |
end | |
-- | |
-- | |
Monster:Initialize() | |
Monster:InitializeUnique() | |
local ExecutableOrders = { | |
}; | |
local EnemyTies = { | |
["Good"] = "Evil"; | |
["Evil"] = "Good"; | |
} | |
ExecutableOrders["MOVETO"] = function(Order) | |
script.Parent.CustomMove.Value = true | |
Pathfinder.Target = Order.MoveToPosition.Value | |
Pathfinder:ComputePath(true) | |
Pathfinder:Start(1,function() | |
if Order.ForceCancel.Value then | |
Pathfinder.Stop("MoveToOrderCancelled") | |
end | |
end) | |
Pathfinder.Stopped:wait() | |
if not Order.ForceCancel.Value then | |
Order.Completed:Fire("Success") | |
else | |
Order.Cancelled:Fire() | |
end | |
script.Parent.CustomMove.Value = true | |
end; | |
ExecutableOrders["ELIMINATE"] = function(Order) | |
Self.CustomMove.Value = true | |
local DeathConnection = nil | |
if script.Parent.Leader.Value ~= nil then | |
local EnemiesContainer =workspace.Mobs | |
if EnemiesContainer then | |
local Enemies = EnemiesContainer | |
if Enemies ~= nil then | |
if #Enemies:GetChildren() > 0 then | |
DeathConnection = Self.Human.Died:connect(function() | |
Pathfinder:Stop("KIA") | |
Target = nil | |
DeathConnection:disconnect() | |
Order.Cancelled:Fire() | |
Order.ForceCancel.Value = true | |
end) | |
for _, enemy in pairs(Enemies:GetChildren()) do | |
if enemy.Name == Order.Target.Value then | |
if enemy:FindFirstChildOfClass("Humanoid") then | |
Target = enemy:FindFirstChildOfClass("Humanoid") | |
Pathfinder.Target = Monster:GetTargetCFrame().p | |
local Distance = (Monster:GetTargetCFrame().p - Monster:GetCFrame().p).magnitude | |
local status = Pathfinder:ComputePath(false) | |
if status == Enum.PathStatus.Success then | |
Pathfinder:Start(1,function() | |
Self.Human.WalkSpeed = 25 if Monster:TargetIsValid() and (Monster:HasClearLineOfSight() or((Monster:GetTargetCFrame().p - Monster:GetCFrame().p).magnitude >= 30)) then | |
Self.Shooting.Value = true | |
Self.Human.WalkSpeed = 0 | |
Self.SetAimed:Fire(true) | |
spawn(function() | |
math.randomseed(tick()) | |
repeat | |
Weapon.TargetCFrame.Value = Monster:GetTargetCFrame() | |
wait() | |
until | |
Self.Human.Health <= 0 or (not Monster:TargetIsValid()) or (not Monster:HasClearLineOfSight()) or (Monster:GetTargetCFrame().p - Monster:GetCFrame().p).magnitude >= 30 | |
Self.FinishedRangeFiring:Fire() | |
end) | |
Self.FinishedRangeFiring.Event:wait() | |
Self.SetAimed:Fire(false) | |
Self.Human.WalkSpeed = 25 | |
Self.Shooting.Value = false | |
end | |
end) | |
Pathfinder.Stopped:wait() | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
Self.CustomMove.Value = false | |
Self.Shooting.Value = false | |
if Order ~= nil then | |
if Order.ForceCancel.Value then | |
Order.Cancelled:Fire() | |
else | |
Order.Completed:Fire("Success") | |
end | |
end | |
end; | |
--ExecutableOrders["FIREONSIGHT"] = function(Order) | |
-- Self.CustomMove.Value = true | |
-- Weapon.ChangeStance:Fire("Normal") | |
-- local DeathConnection = nil | |
-- if script.Parent.Leader.Value ~= nil then | |
-- DeathConnection = Self.Human.Died:connect(function() | |
-- Pathfinder:Stop("KIA") | |
-- Mind.CurrentTargetHumanoid.Value = nil | |
-- DeathConnection:disconnect() | |
-- Order.Cancelled:Fire() | |
-- Order.ForceCancel.Value = true | |
-- end) | |
-- repeat | |
-- | |
-- local npcs = getEnemies(workspace.Mobs) | |
-- for _, npc in pairs(npcs) do | |
-- if npc:FindFirstChildOfClass("Humanoid") then | |
-- Mind.CurrentTargetHumanoid.Value = npc:FindFirstChildOfClass("Humanoid") | |
-- end | |
-- if Monster:TargetIsValid() then | |
-- Monster:Talk("Target sighted, getting into position, sir!") | |
-- local FPs = Locale.FiringPositions:GetChildren() | |
-- local FP = FPs[math.random(#FPs)] | |
-- Self.Human:MoveTo(FP.CFrame.p) | |
-- repeat wait() until (FP.CFrame.p - Monster:GetCFrame().p).magnitude <= 10 | |
-- print("Going prone for targets...") | |
-- Self.CurrentItem.Value.ChangeStance:Fire("Crouch",true) | |
-- Self.CurrentItem.Value.ChangeStance:Fire("Prone",true) | |
-- Weapon.TargetCFrame.Value = Monster:GetTargetCFrame() | |
-- Monster:Talk("Firing!") | |
-- Self.SetAimed:Fire(true) | |
-- Self.Shooting.Value = true | |
-- repeat | |
-- Weapon.TargetCFrame.Value = Monster:GetTargetCFrame() | |
-- wait() | |
-- until | |
-- Mind.CurrentTargetHumanoid.Value.Health <= 0 or (Monster:GetTargetCFrame().p - Monster:GetCFrame().p).magnitude > Monster:GetMaximumDetectionDistance() | |
-- | |
-- Self.Shooting.Value = false | |
-- Self.CurrentItem.Value.ChangeStance:Fire("Prone",false) | |
-- Self.CurrentItem.Value.ChangeStance:Fire("Crouch",false) | |
-- Self.SetAimed:Fire(false) | |
-- | |
-- end | |
-- if (Weapon.StoredAmmo.Value == 0 and Weapon.Ammo.Value == 0) then | |
-- Pathfinder:Stop("OutOfAmmo") | |
-- Monster:Talk("Sir, I'm outta ammo!") | |
-- Mind.CurrentTargetHumanoid.Value = nil | |
-- Order.ForceCancel.Value = true | |
-- break | |
-- end | |
-- if Order == nil then | |
-- break | |
-- end | |
-- end | |
-- | |
-- wait() | |
-- until | |
-- Self.Human.Health <= 0 | |
-- end | |
-- Self.Shooting.Value = false | |
-- Self.CustomMove.Value = false | |
-- if Order ~= nil then | |
-- if Order.ForceCancel.Value then | |
-- Order.Cancelled:Fire() | |
-- else | |
-- Order.Completed:Fire("Success") | |
-- end | |
-- end | |
--end; | |
function getCoverPoints() | |
local cPoints = {} | |
for _, point in pairs(workspace.CoverSystem.CoverObjects:GetChildren()) do | |
if point:IsA("Model") then | |
if point.Name:find("AI") then | |
table.insert(cPoints,point:FindFirstChild("AICoverSpawn")) | |
end | |
end | |
end | |
return cPoints | |
end; | |
ExecutableOrders["BAIL"] = function(Order) | |
Self.CustomMove.Value = true | |
Self.Human.Jump = true | |
Self.Human:Move(Self.Head.CFrame.lookVector) | |
wait(2) | |
Self.Human.Jump = true | |
wait(0.5) | |
Self.Human:Move(Vector3.new()) | |
Self.Stats.Bailing.Value = true | |
Self.LandedFromBail.Event:wait() | |
Self.CustomMove.Value = false | |
Order.Completed:Fire("Success") | |
end | |
Self.RunAuxillary.Event:connect(function(reason,point,spawnPoint,ts) | |
if reason == "Extraction-Escape" then | |
Self.CancelCurrentOrder:Fire() | |
Self.CustomMove.Value = true | |
Pathfinder.Target = point | |
Pathfinder:ComputePath(true) | |
Self.Human.WalkSpeed = 25; | |
Pathfinder:Start(1,function() | |
end) | |
Pathfinder.Stopped:wait() | |
Monster:Talk("Sir, I'm at the extraction point, and I'm entering the ship!") | |
Self.PrimaryPart.CFrame = ts.Bodykit.TroopPlacement:GetChildren()[Self.ID.Value].SkateboardPlatform.CFrame + Vector3.new(0,3,0) | |
Self.CustomMove.Value = false | |
end | |
end) | |
local bindableService = require(game.ReplicatedStorage.BindingService)() | |
function getEnemiesInRange() | |
local result = {} | |
for _, enemy in pairs(workspace.Mobs:GetChildren()) do | |
if enemy then | |
if enemy:FindFirstChildOfClass("Humanoid") then | |
if require(enemy.BOT).Allegiance ~= BOTBrain.Allegiance and enemy.PrimaryPart then | |
local distance = (enemy.PrimaryPart.CFrame.p - Self.PrimaryPart.CFrame.p).magnitude | |
if distance < BOTBrain.ChaseRange then | |
result[#result+1] = enemy | |
end | |
end | |
end | |
end | |
end | |
for _, enemy in pairs(bindableService.fetch("PlayerList")) do | |
if enemy then | |
if enemy.Character then | |
if enemy.Character:FindFirstChildOfClass("Humanoid") then | |
if enemy.Allegiance.Value ~= BOTBrain.Allegiance then | |
local distance = (enemy.Character.PrimaryPart.CFrame.p - Self.PrimaryPart.CFrame.p).magnitude | |
if distance < BOTBrain.ChaseRange then | |
result[#result+1] = enemy.Character | |
for _, secondEnemy in pairs(enemy.playerArmy.Value:GetChildren()) do | |
if secondEnemy:FindFirstChildOfClass("Humanoid") and secondEnemy.PrimaryPart then | |
local distance = (secondEnemy.PrimaryPart.CFrame.p - Self.PrimaryPart.CFrame.p).magnitude | |
if distance < BOTBrain.ChaseRange then | |
result[#result+1] = secondEnemy | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
return result | |
end | |
ExecutableOrders["ELIMINATE3"] = function(Order) | |
Self.CustomMove.Value = true | |
local enemies = Monster:GetClosestEnemiesWithCount(3) | |
if #enemies > 0 then | |
for _, enemy in pairs(enemies) do | |
if enemy then | |
local eHum = enemy:FindFirstChildOfClass("Humanoid") | |
if eHum then | |
Target = eHum | |
Pathfinder.Target = Monster:GetTargetCFrame().p | |
local Distance = (Monster:GetTargetCFrame().p - Monster:GetCFrame().p).magnitude | |
local status = Pathfinder:ComputePath(false) | |
if status == Enum.PathStatus.Success then | |
Pathfinder:Start(1,function() | |
Self.Human.WalkSpeed = 25 | |
if Monster:TargetIsValid() and (Monster:HasClearLineOfSight() or((Monster:GetTargetCFrame().p - Monster:GetCFrame().p).magnitude >= 30)) then | |
Self.Shooting.Value = true | |
Self.Human.WalkSpeed = 0 | |
Self.SetAimed:Fire(true) | |
repeat | |
Weapon.TargetCFrame.Value = Monster:GetTargetCFrame() | |
wait() | |
until | |
Self.Human.Health <= 0 or (not Monster:TargetIsValid()) or (Monster:GetTargetCFrame().p - Monster:GetCFrame().p).magnitude >= 30 or not Monster:HasClearLineOfSight() | |
Self.SetAimed:Fire(false) | |
Self.Human.WalkSpeed = 25 | |
Self.Shooting.Value = false | |
end | |
end) | |
Pathfinder.Stopped:wait() | |
end | |
end | |
end | |
end | |
end | |
Order.Completed:Fire("Success") | |
Self.CustomMove.Value = false | |
end | |
ExecutableOrders["SCOUTAHEAD"] = function(Order) | |
end | |
ExecutableOrders["CLEARZONE"] = function(Order) | |
Self.CustomMove.Value = true | |
local enemies = getEnemiesInRange() | |
for _, enemy in pairs(enemies) do | |
if enemy then | |
local eHum = enemy:FindFirstChildOfClass("Humanoid") | |
if eHum then | |
Target = eHum | |
Pathfinder.Target = Monster:GetTargetCFrame().p | |
local Distance = (Monster:GetTargetCFrame().p - Monster:GetCFrame().p).magnitude | |
local status = Pathfinder:ComputePath(false) | |
if status == Enum.PathStatus.Success then | |
Pathfinder:Start(1,function() | |
Self.Human.WalkSpeed = 25 | |
if Monster:TargetIsValid() and (Monster:HasClearLineOfSight() or((Monster:GetTargetCFrame().p - Monster:GetCFrame().p).magnitude >= 30)) then | |
Self.Shooting.Value = true | |
Self.Human.WalkSpeed = 0 | |
Self.SetAimed:Fire(true) | |
spawn(function() | |
math.randomseed(tick()) | |
repeat | |
Weapon.TargetCFrame.Value = Monster:GetTargetCFrame() | |
wait() | |
until | |
Self.Human.Health <= 0 or (not Monster:TargetIsValid()) or (Monster:GetTargetCFrame().p - Monster:GetCFrame().p).magnitude >= 30 | |
Self.FinishedRangeFiring:Fire() | |
end) | |
Self.FinishedRangeFiring.Event:wait() | |
Self.SetAimed:Fire(false) | |
Self.Human.WalkSpeed = 25 | |
Self.Shooting.Value = false | |
end | |
end) | |
end | |
end | |
end | |
end | |
Self.CustomMove.Value = false | |
end | |
return ExecutableOrders |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Quest = {} | |
local RemoteService = require(game.ReplicatedStorage.RemoteService) | |
local ProgressionService = require(game.ReplicatedStorage.ProgressionService) | |
local AnalyticsService = require(game.ReplicatedStorage.AnalyticsService) | |
Quest.__index = Quest | |
function Quest.new(...) | |
local q = {} | |
local args = {...} | |
q.Name = args[1]; | |
q.Plr = args[2]; | |
q.Objectives = {}; | |
q.Description = args[3]; | |
q.Reward = args[4]; | |
q.Reward.Parent = q | |
return setmetatable(q,Quest) | |
end | |
function Quest:AddObjective(objective) | |
self.Objectives[#self.Objectives+1] = objective | |
return #self.Objectives | |
end | |
function Quest:CompleteObjective(index) | |
self.Objectives[index]:Complete(function(obj) | |
RemoteService.send("Client",self.Plr,"CompleteObjective",obj.Name) | |
ProgressionService:AddXP(self.Plr,obj.XPGain,"ObjectiveComplete") | |
end) | |
end | |
function Quest:RemoveObjective(index) | |
self.Objectives[index] = nil | |
end | |
function Quest:GetObjectives() | |
local result = {} | |
for i, objective in pairs(self.Objectives) do | |
if objective then | |
result[#result+1] = objective:ToReplicatedObjective() | |
end | |
end | |
return result | |
end | |
function Quest:GetObjectiveByName(name) | |
local result = nil | |
local index = 0 | |
for i, objective in pairs(self.Objectives) do | |
if objective.Name == name then | |
result = objective | |
index = i | |
end | |
end | |
return result, index | |
end | |
function Quest:Give() | |
local qrType = self.Reward.Type | |
if qrType == "cR" then | |
self.Plr.leaderstats.Credits.Value = self.Plr.leaderstats.Credits.Value + self.Reward.Amount | |
elseif qrType == "XP" then | |
ProgressionService:AddXP(self.Plr,self.Reward.Amount,"QuestComplete") | |
elseif typeof(qrType) == "Instance" and qrType:IsA("Tool") then | |
local qrTypeClone = qrType:Clone() | |
qrTypeClone.Parent = self.Plr.Inventory | |
elseif qrType == "squadMember" then | |
print("Unimplemented SQUAD Reward") | |
end | |
end | |
function Quest:Complete() | |
self:Give() | |
AnalyticsService.RecordQuestProgress(self.Plr,"Complete",self.Reward.Amount,self.Name,"Quest") | |
-- Add More Completion Logic here. | |
end | |
function Quest:GiveObjectives() | |
RemoteService.send("Client",self.Plr,"DisplayObjectives",self:GetObjectives()) | |
end | |
return Quest |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local QuestService = {} | |
QuestService.ReplicatedStorage = game:GetService("ReplicatedStorage") | |
QuestService.QuestObj = require(script.Quest) | |
QuestService.Archetypes = require(script.QuestArcheTypes) | |
QuestService.Quests = {} | |
QuestService.CurrentQuest = {} | |
QuestService.Objective = require(script.Objective) | |
local BindingService = require(game.ReplicatedStorage.BindingService)() | |
QuestService.RewardObj = require(script.Reward); | |
local RunService = game:GetService("RunService") | |
QuestService.Extensions = { | |
["Server"] = { | |
}; | |
["Client"] = { | |
} | |
} | |
QuestService.Handlers = { | |
["ObjectiveComplete"] = function() end; | |
["StartQuest"] = function() end; | |
} | |
QuestService.Quests = {} | |
game.Players.PlayerAdded:connect(function(plr) | |
QuestService.Quests[plr.UserId] = {} | |
QuestService.CurrentQuest[plr.UserId] = nil | |
end) | |
game.Players.PlayerRemoving:connect(function(plr) | |
QuestService.Quests[plr.UserId] = nil | |
end) | |
local RemoteService = require(game.ReplicatedStorage.RemoteService) | |
function QuestService:CreateQuest(plr,name,...) | |
if QuestService.CurrentQuest[plr.UserId] then return end | |
QuestService.Quests[plr.UserId][name] = QuestService.QuestObj.new(...) | |
QuestService.CurrentQuest[plr.UserId] = QuestService.Quests[plr.UserId][name] | |
return QuestService.Quests[plr.UserId][name] | |
end | |
function QuestService:AddExtension(name,modelType,funcTable) | |
if not (funcTable["Fetch"] or funcTable["Send"] or funcTable["Bounce"]) then return end | |
QuestService.Extensions[modelType] = funcTable | |
end | |
function QuestService:CreateObjective(name,description,quest) | |
return QuestService.Objective.new(name,description,quest) | |
end | |
function QuestService.startServer() | |
local funcs = { | |
["Server"] = { | |
["Send"] = {}; | |
["Fetch"] = {}; | |
["Bounce"] = {}; | |
}; | |
["Client"] = { | |
["Send"] = {}; | |
["Fetch"] = {}; | |
["Bounce"] = {}; | |
}; | |
} | |
if RunService:IsServer() then | |
for _, funcTable in pairs(QuestService.Extensions["Server"]) do | |
if funcTable["Send"] then | |
for extensionName, extensionCodebase in pairs(funcTable["Send"]) do | |
funcs["Server"]["Send"][extensionName] = extensionCodebase | |
end | |
end | |
if funcTable["Fetch"] then | |
for extensionName, extensionCodebase in pairs(funcTable["Fetch"]) do | |
funcs["Server"]["Fetch"][extensionName] = extensionCodebase | |
end | |
end | |
if funcTable["Bounce"] then | |
for extensionName, extensionCodebase in pairs(funcTable["Bounce"]) do | |
funcs["Server"]["Bounce"][extensionName] = extensionCodebase | |
end | |
end | |
end | |
else | |
for _, funcTable in pairs(QuestService.Extensions["Client"]) do | |
if funcTable["Send"] then | |
for extensionName, extensionCodebase in pairs(funcTable["Send"]) do | |
funcs["Client"]["Send"][extensionName] = extensionCodebase | |
end | |
end | |
if funcTable["Fetch"] then | |
for extensionName, extensionCodebase in pairs(funcTable["Fetch"]) do | |
funcs["Client"]["Fetch"][extensionName] = extensionCodebase | |
end | |
end | |
if funcTable["Bounce"] then | |
for extensionName, extensionCodebase in pairs(funcTable["Bounce"]) do | |
funcs["Client"]["Bounce"][extensionName] = extensionCodebase | |
end | |
end | |
end | |
end | |
RemoteService.listen("Server","Send","RunExtension",function(player,...) | |
end) | |
RemoteService.listen("Server","Fetch","InvokeExtension",function(player,extension,...) | |
local args = {...} | |
return funcs["Server"]["Fetch"][extension](...) | |
end) | |
RemoteService.listen("Server","Bounce","RunGlobalExtension",function(player,...) | |
end) | |
end | |
function QuestService:CreateFromArchetype(aType,plr,...) | |
local args = {...} | |
if not plr then return nil end | |
if not aType then error("QuestService: Archetype MUST be specified to create quest.") end | |
local archeType = QuestService.Archetypes[aType]; | |
local ArchetypeQuest | |
if archeType then | |
ArchetypeQuest = QuestService.QuestObj.new(archeType.Name(args[1]),plr,archeType.Description(args[1]),QuestService.RewardObj.new(archeType.Reward.Type,archeType.Reward.Amount(),archeType.Reward.ExtraData)) | |
for _, objective in pairs(archeType.Objectives) do | |
ArchetypeQuest:AddObjective(QuestService.Objective.new(objective.Name,objective.Text,ArchetypeQuest)) | |
end | |
end | |
if ArchetypeQuest then | |
QuestService.Quests[plr.UserId][ArchetypeQuest.Name] = ArchetypeQuest | |
end | |
QuestService.Handlers["StartQuest"](plr,ArchetypeQuest) | |
return ArchetypeQuest.Name | |
end | |
function QuestService:BroadcastToOwner(plr,qName) | |
local quest = QuestService.Quests[plr.UserId][qName]; | |
if quest then | |
local KillChanged = {} | |
for i, obj in pairs(quest.Objectives) do | |
if obj.Type == "Kill" then | |
KillChanged[i] = game.ServerScriptService.KillAdded.Event:connect(function(kill) | |
local killed = kill.Killed | |
if killed.Name == self.Goal then | |
self.CompletedGoalCount = self.CompletedGoalCount + 1 | |
if self.CompletedGoalCount == self.GoalCount then | |
self:Complete(function() | |
KillChanged[i]:disconnect() | |
end) | |
end | |
end | |
end) | |
end | |
end | |
quest:GiveObjectives() | |
end | |
end | |
function QuestService:MarkObjectiveAsComplete(plr,questName,objectiveName) | |
local quest = QuestService.Quests[plr.UserId][questName] | |
if quest then | |
local objective, oI = quest:GetObjectiveByName(objectiveName) | |
if objective and oI ~= 0 then | |
quest:CompleteObjective(oI) | |
QuestService.Handlers["ObjectiveComplete"](plr,objective,quest) | |
end | |
end | |
end | |
function QuestService:CompleteQuest(plr,qName) | |
local quest = QuestService.Quests[plr.UserId][qName] | |
if quest then | |
quest:Complete() | |
QuestService.Quests[plr.UserId][qName] = nil | |
QuestService.CurrentQuest[plr.UserId] = nil | |
end | |
end | |
function QuestService:HasQuest(plr,qName) | |
return QuestService.Quests[plr.UserId][qName] ~= nil | |
end | |
--function QuestService:GetDialog(QuestID) | |
-- return QuestService.Dialogs.dialog[QuestID] | |
--end | |
--function QuestService:SerializeQuest(Quest_Folder) | |
-- local Quest = {} | |
-- Quest.ID = Quest_Folder.Name | |
-- Quest.Number = Quest_Folder.Number.Value | |
-- Quest.Goal = Quest_Folder.Goal.Value | |
-- Quest.IsComplete = Quest_Folder.IsComplete.Value | |
-- Quest.OnQuest = Quest_Folder.OnQuest.Value | |
-- Quest.DialogCompleted_Blurb = Quest_Folder.DialogCompleted_Blurb.Value | |
-- Quest.QuestTitle = Quest_Folder.QuestTitle.Value | |
-- if Quest_Folder.Type == nil then return Quest end | |
-- Quest.Type = Quest_Folder.Type.Value | |
-- return Quest | |
--end | |
--function QuestService:CreateTutorialTag(QuestID,Quest_Data,player) | |
-- local Tag = QuestService.QuestTag:Clone() | |
-- Tag.Name = QuestID | |
-- Tag.Status.Text = " 0 / " .. #Quest_Data["Steps"] | |
-- Tag.Title.Text = Quest_Data["Name"] | |
-- Tag.Parent = player.PlayerGui.QUG.Container | |
-- return Tag,Quest_Data["Steps"] | |
--end | |
--function QuestService:CreateTutorialFolder(QuestID,Quest_Data) | |
-- | |
-- local folder = Instance.new("Folder") | |
-- folder.Name = QuestID | |
-- | |
-- local number_value = Instance.new("IntValue",folder) | |
-- number_value.Name = "Number" | |
-- local steps = Quest_Data["Steps"] | |
-- local goal = Instance.new("IntValue",folder) | |
-- goal.Name = "StepsRemaining" | |
-- goal.Value = #steps | |
-- return folder | |
--end | |
--function QuestService:StartQuest(QuestID,Quest_Data,Dialog_Data) | |
-- local folder = Instance.new("Folder") | |
-- folder.Name = QuestID | |
-- | |
-- | |
-- local title = Instance.new("StringValue",folder) | |
-- title.Name = "QuestTitle" | |
-- title.Value = Quest_Data["Name"] | |
-- | |
-- local OnQuest = Instance.new("BoolValue",folder) | |
-- OnQuest.Name = "OnQuest" | |
-- OnQuest.Value = true | |
-- | |
-- local number_value = Instance.new("IntValue",folder) | |
-- number_value.Name = "Number" | |
-- | |
-- local isComplete = Instance.new("BoolValue",folder) | |
-- isComplete.Name = "IsComplete" | |
-- isComplete.Value = false | |
--if Quest_Data["Type"] == "EXTRACTION" then | |
-- local BaseSecured = Instance.new("BoolValue") | |
-- BaseSecured.Name = "BaseSecured" | |
-- BaseSecured.Value = false | |
-- BaseSecured.Parent = folder | |
-- | |
--elseif Quest_Data["Type"] == "SLAY" then | |
-- local goal = Instance.new("IntValue",folder) | |
-- goal.Name = "Goal" | |
-- goal.Value = Quest_Data["Nmbr"] | |
--end | |
-- | |
-- local Dialog_Complete = Instance.new("StringValue",folder) | |
-- Dialog_Complete.Name = "DialogCompleted_Blurb" | |
-- Dialog_Complete.Value = Dialog_Data["Quest"]["COMPLETE"] | |
-- | |
-- local Quest_Type = Instance.new("StringValue",folder) | |
-- Quest_Type.Name = "Type" | |
-- Quest_Type.Value = Quest_Data["Type"] | |
-- | |
-- | |
-- return folder | |
--end | |
-- | |
-- | |
--function QuestService:SaveChanges(player,Folder) | |
-- pcall(function() QuestService.QuestStorage:PostAsync(player.UserId.."-quest",QuestService:SerializeQuest(Folder)) end) | |
-- | |
--end | |
-- | |
--function QuestService:WarnPlayerOfIncompleteQuest(NPCDialog,Dialog_Data,Decline_Btn) | |
-- NPCDialog.Text = " " .. Dialog_Data["Quest"]["INCOMPLETE"] | |
-- Decline_Btn.Text = "Oh , right!" | |
-- | |
--end | |
-- | |
--local year = 1970 | |
--local month = 1 | |
--local day = 1 | |
--local Date = "January 1, 1970" | |
-- | |
--local hour = 0 | |
--local min = 0 | |
--local sec = 0 | |
--local tag = "AM" | |
--local Time = "12:00 AM" | |
-- | |
--function QuestService.getDate() | |
-- | |
--local Type = 0 | |
--local Sec = true | |
-- local t = tick() | |
-- local months = { | |
---- {"MONTH", TOAL DAYS TO YEAR, DAYS} <- Format | |
-- {"January",31,31}; | |
-- {"February",59,28}; | |
-- {"March",90,31}; | |
-- {"April",120,30}; | |
-- {"May",151,31}; | |
-- {"June",181,30}; | |
-- {"July",212,31}; | |
-- {"August",243,31}; | |
-- {"September",273,30}; | |
-- {"October",304,31}; | |
-- {"November",334,30}; | |
-- {"December",365,31}; | |
-- } | |
-- year = math.floor(1970+(t/31579200)) | |
-- if ((year%4) == 0) then -- Check for leap year | |
-- months[2][3] = 29 | |
-- for i,v in pairs(months) do | |
-- if (i ~= 1) then | |
-- v[2] = (v[2]+1) | |
-- end | |
-- end | |
-- end | |
-- day = math.floor(((t/86400)%365.25)+1) -- Get current day of the year. Starts at 0, so 1 is added (365.25 is the average # of days in a year due to leap year) | |
-- for i,m in pairs(months) do | |
-- if ((m[2]-m[3]) <= day) then -- Get month based on day | |
-- month = i | |
-- end | |
-- end | |
-- local m = months[month] | |
-- day = (day+m[3]-m[2]) -- Get day of the month | |
-- year,day = tostring(year),tostring(day) | |
-- local c,s = ", "," " -- Comma, space | |
-- Date = (months[month][1] .. s .. day .. c .. year) | |
-- return Date | |
--end | |
-- | |
--function QuestService.getTime() | |
-- | |
-- | |
--local Type = 0 | |
--local Sec = true | |
-- local t = tick() | |
-- local sec = math.floor((t%60)) -- Sec, Min, and Hour equations I actually got off of Google. Everything else was written by me | |
-- local min = math.floor((t/60)%60) | |
-- local hour = math.floor((t/3600)%24) | |
-- sec = tostring((sec < 10 and "0" or "") .. sec) | |
-- min = tostring((min < 10 and "0" or "") .. min) | |
-- tag = (Type == 0 and (hour < 12 and "AM" or "PM") or "") | |
-- hour = ((Type == 1 and hour < 10 and "0" or "") .. tostring(Type == 0 and (hour == 0 and 12 or hour > 12 and (hour-12) or hour) or hour)) -- Ternary operators FTW. Helps get rid of 'if then' stuff. Actually learned this off of Java programming: z = (x == y ? "Yes" : "No") | |
-- local c,s = ":",(Type == 0 and " " or "") -- Colon, (space if 12 hr clock) | |
-- Time = (hour .. c .. min .. (Sec and c .. sec or "") .. s .. tag) | |
-- return Time | |
--end | |
--function QuestService:GetCompletedQuest(player,QuestID) | |
-- return QuestService.CompletedQuestStorage:GetAsync(player.UserId.."-completed-quest-"..QuestID,{ | |
-- DecodeJSON = true | |
-- }) | |
--end | |
--function QuestService:EraseCompletedQuest(player,QuestID) | |
-- return QuestService.CompletedQuestStorage:PostAsync(player.UserId.."-completed-quest-"..QuestID,{}) | |
--end | |
--function QuestService:MarkCompletion(player,Folder) | |
-- local CompletionDate = QuestService.getDate().." , "..QuestService.getTime() | |
-- pcall(function()QuestService.CompletedQuestStorage:PostAsync(player.UserId.."-completed-quest-"..Folder.Name,{ | |
-- Name = Folder.Name, | |
-- CompletionDate = CompletionDate | |
-- | |
-- }) | |
-- end) | |
-- | |
--end | |
--function QuestService:RewardPlayer(player,Folder,QuestTag,GUI,removeTag,extractionQuest) | |
-- if QuestService.Quests.quests[Folder.Name] and not extractionQuest then | |
-- player:WaitForChild("leaderstats").XP.Value = player:WaitForChild("leaderstats").XP.Value + QuestService.Quests.quests[Folder.Name]["EXPg"] | |
-- player:WaitForChild("leaderstats").Credits.Value = player:WaitForChild("leaderstats").Credits.Value + QuestService.Quests.quests[Folder.Name]["GLDg"] | |
-- elseif QuestService.Quests.quests[Folder.Name]["StepQuests"][extractionQuest.Name] then | |
-- player:WaitForChild("leaderstats").XP.Value = player:WaitForChild("leaderstats").XP.Value + QuestService.Quests.quests[Folder.Name]["StepQuests"][extractionQuest.Name]["EXPg"] | |
-- player:WaitForChild("leaderstats").Credits.Value = player:WaitForChild("leaderstats").Credits.Value + QuestService.Quests.quests[Folder.Name]["StepQuests"][extractionQuest.Name]["GLDg"] | |
-- end | |
-- QuestService:MarkCompletion(player,Folder) | |
-- Folder:Destroy() | |
-- if removeTag then | |
-- QuestTag:Destroy() | |
-- end | |
-- game.ReplicatedStorage.RemoteService.QuestTagResolve:FireClient(player) | |
-- pcall(function() QuestService.QuestStorage:PostAsync(player.UserId.."-quest",{}) end) | |
-- player.CurrentQuest.Value = "None" | |
--if QuestService:GetQuestData(Folder.Name)["ContinuityQuest"] then | |
-- game.ReplicatedStorage.RemoteService.IntroduceTutorial:FireClient(player) | |
--end | |
-- GUI:Destroy() | |
--end | |
-- | |
--function QuestService:EnableTrackedChanges(player,Folder,Status) | |
-- Folder.Number.Changed:connect(function(value) | |
-- Status.Text = tostring(value) .. " / " .. tostring(Folder.Goal.Value) | |
-- if value >= Folder.Goal.Value then | |
-- Folder.IsComplete.Value = true | |
-- | |
-- end | |
-- QuestService:SaveChanges(player,Folder) | |
-- | |
-- | |
-- end) | |
-- | |
--end | |
-- | |
--function QuestService:ExtractData(Dialog_Data) | |
-- return Dialog_Data["EXIT"] | |
--end | |
-- | |
--function QuestService:GetDialogCount(Dialog_Data) | |
-- local num_of_dialogs = 0 | |
-- for key, value in pairs(Dialog_Data["NoQuest"]) do | |
-- if key ~= "EXIT" then | |
-- num_of_dialogs = num_of_dialogs + 0.5 | |
-- end | |
-- end | |
-- return num_of_dialogs | |
--end | |
--function QuestService:DisplayInitialDialogData(Dialog_Data,NPCDialog,dialog_num,Accept_Btn) | |
-- | |
-- NPCDialog.Text = Dialog_Data["NoQuest"]["NPC"..dialog_num] | |
-- | |
-- | |
-- Accept_Btn.Text = Dialog_Data["NoQuest"]["RES"..dialog_num] | |
--end | |
--function QuestService:EnableDialogChanges(player,Accept_Btn,Decline_Btn,NPCDialog,GUI,QuestTag,Folder) | |
-- Accept_Btn.Visible = false | |
-- | |
-- NPCDialog.Text = " " .. Folder.DialogCompleted_Blurb.Value | |
-- Decline_Btn.Text = "Thanks!" | |
-- Decline_Btn.MouseButton1Click:connect(function() | |
-- QuestService:RewardPlayer(player,Folder,QuestTag,GUI,true) | |
-- end) | |
--end | |
--function QuestService:GetQuest(player,Quest) | |
-- return player:FindFirstChild(Quest) | |
-- | |
--end | |
--function QuestService:CreateTag(Folder) | |
-- local Tag = QuestService.QuestTag:Clone() | |
-- Tag.Name = Folder.Name | |
-- if Folder.Type.Value ~= "EXTRACTION" then | |
-- Tag.Status.Text = " 0 / " .. Folder.Goal.Value | |
-- else | |
-- Tag.Status.Text = "BASE " .. (Folder.BaseSecured.Value and "SECURED" or "VULNERABLE") | |
-- end | |
-- Tag.Title.Text = Folder.QuestTitle.Value | |
-- return Tag | |
--end | |
--function QuestService:CreateSavedTag(Folder) | |
-- local QT = QuestService:CreateTag(Folder) | |
-- QT.Name = Folder.Name | |
-- | |
-- QT.Status.Text = " "..Folder.Number.Value.." / ".. Folder.Goal.Value | |
-- QT.Title.Text = Folder.QuestTitle.Value | |
-- return QT | |
-- | |
-- | |
--end | |
--function QuestService:CreateSavedTutorialTag(Folder) | |
-- local QT = QuestService:CreateTutorialTag(Folder.Name) | |
-- QT.Status.Text = " "..Folder.Number.Value.." / ".. Folder.Goal.Value | |
-- QT.Title.Text = Folder.QuestTitle.Value | |
--end | |
-- | |
--function QuestService:EnableQuestResummoningOnDeath(player,Quest,GUIContainer,Quest_Data,Dialog_Data) | |
-- player.Character.Humanoid.Died:connect(function() | |
-- player.CharacterAdded:wait() | |
-- local Quest_Tag = QuestService:CreateSavedTag(QuestService:GetQuest(player,Quest)) | |
-- Quest_Tag.Parent = GUIContainer | |
-- local Status = GUIContainer:FindFirstChild("Status", true) | |
-- QuestService:EnableTrackedChanges(player,QuestService:GetQuest(player,Quest),Status) | |
--end) | |
--end | |
--function QuestService:EnableTutorialResummoningOnDeath(player,Quest,GUIContainer) | |
-- local Quest_Tag = QuestService:CreateSavedTutorialTag(QuestService:GetQuest(player,Quest)) | |
-- Quest_Tag.Parent = GUIContainer | |
-- local Status = GUIContainer:FindFirstChild("Status", true) | |
-- QuestService:EnableTrackedChanges(QuestService:GetQuest(player,Quest),Status) | |
--end | |
--function QuestService:LoadQuest(player) | |
-- return QuestService.QuestStorage:GetAsync(player.UserId.."-quest",{ | |
-- DecodeJSON = true | |
-- }) | |
-- | |
--end | |
--function QuestService:QuestEntryToFolder(QuestInfo) | |
-- | |
-- if QuestInfo == nil then return end | |
-- local folder = Instance.new("Folder") | |
-- folder.Name = QuestInfo.ID or "" | |
-- | |
-- | |
-- local title = Instance.new("StringValue") | |
-- title.Name = "QuestTitle" | |
-- title.Value = QuestInfo.QuestTitle | |
-- title.Parent = folder | |
-- local OnQuest = Instance.new("BoolValue") | |
-- OnQuest.Name = "OnQuest" | |
-- OnQuest.Value = QuestInfo.OnQuest | |
-- OnQuest.Parent = folder | |
-- if QuestInfo.Type == "SLAY" then | |
-- local number_value = Instance.new("IntValue") | |
-- number_value.Name = "Number" | |
-- number_value.Value = QuestInfo.Number | |
-- number_value.Parent = folder | |
-- local goal = Instance.new("IntValue") | |
-- goal.Name = "Goal" | |
-- goal.Value = QuestInfo.Goal | |
-- goal.Parent = folder | |
-- elseif QuestInfo.Type == "EXTRACTION" then | |
-- | |
-- end | |
-- local isComplete = Instance.new("BoolValue",folder) | |
-- isComplete.Name = "IsComplete" | |
-- isComplete.Value = QuestInfo.IsComplete | |
-- isComplete.Parent = folder | |
-- | |
-- local Dialog_Complete = Instance.new("StringValue") | |
-- Dialog_Complete.Name = "DialogCompleted_Blurb" | |
-- Dialog_Complete.Value = QuestInfo.DialogCompleted_Blurb | |
-- Dialog_Complete.Parent = folder | |
-- local Quest_Type = Instance.new("StringValue") | |
-- Quest_Type.Name = "Type" | |
-- Quest_Type.Value = QuestInfo.Type | |
-- Quest_Type.Parent = folder | |
-- | |
-- | |
-- return folder | |
--end | |
-- | |
return QuestService |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Reward = {} | |
Reward.__index = Reward | |
function Reward.new(...) | |
local rw = {} | |
local args = {...} | |
rw.Type = args[1] | |
rw.Amount = args[2] | |
rw.ExtraData = args[3] | |
return setmetatable(rw,Reward) | |
end | |
return Reward |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Engine = script.Parent.Main.Parts.Engine | |
local parts = script.Parent.Main.Parts | |
game.CollectionService:AddTag(script.Parent,game.HttpService:GenerateGUID(false)) | |
local DamageTag = require(game.ReplicatedStorage.DamageTag) | |
repeat wait() until script.Parent.Welded.Value == true | |
local TurretWeld = script.Parent.Main.Parts.TurretRing1.TurretRingWeld | |
local Settings = require(script.Parent.SETTINGS) | |
local RS = game:GetService("RunService") | |
local Others = require(workspace.Settings.Others) | |
local CEIL = math.ceil | |
local CF = CFrame.new | |
local Tank = script.Parent | |
local Bot = require(Tank.BOT) | |
local PFS = game:GetService("PathfindingService") | |
local Mind = Tank.Mind | |
local bindableService = require(game.ReplicatedStorage.BindingService)() | |
local RAY = Ray.new | |
local HUGE = math.huge | |
local function tagHumanoid(humanoid,dmg) | |
local tag = DamageTag.new((game.Players:GetPlayerFromCharacter(humanoid.Parent) and game.CollectionService:GetTags(game.Players:GetPlayerFromCharacter(humanoid.Parent))[1] or game.CollectionService:GetTags(humanoid.Parent)[1]),dmg,game.CollectionService:GetTags(Tank)[1],game.CollectionService:GetTags(Tank)[1]) | |
tag:MarkEnemy(humanoid) | |
end | |
local Data = { | |
-- These are variable values used internally by the script. Advanced users only. | |
LastRecomputePath = 0, | |
Recomputing = false, -- Reocmputing occurs async, meaning this script will still run while it's happening. This variable will prevent the script from running two recomputes at once. | |
CurrentNode = nil, | |
CurrentNodeIndex = 1, | |
AutoRecompute = true, | |
LastJumpCheck = 0, | |
LastAttack = 0, | |
EnemyAllegiance = ""; | |
AttackTrack = nil, | |
} | |
local RayCast = workspace.FindPartOnRayWithIgnoreList | |
Engine.BodyVelocity.MaxForce = Vector3.new(HUGE,HUGE,HUGE) | |
Engine.BodyGyro.MaxTorque = Vector3.new(4e8,4e8,4e8) | |
function castray(cframeFirst, cframeSecond, ignoreObject, distanceToCast) | |
local newRay = Ray.new(cframeFirst.p, (cframeSecond.p - cframeFirst.p).unit * distanceToCast) | |
local hitObject, positionHit = workspace:FindPartOnRay(newRay, ignoreObject) | |
return positionHit, hitObject | |
end | |
local function canSeeTarget(target) | |
local ray = Ray.new(Engine.CFrame.p,Engine.CFrame.lookVector * 200) | |
local H,P,N,M =game.Workspace:FindPartOnRayWithIgnoreList(ray,{script.Parent}) | |
if H then | |
if H:IsDescendantOf(target) then | |
return true | |
end | |
return false | |
end | |
return false | |
end | |
local ProgressionService = require(game.ReplicatedStorage.ProgressionService) | |
function isInPeople(first, second) | |
for _,v in pairs(first) do | |
if second == v then | |
return true | |
end | |
end | |
return false | |
end | |
function getIndexOfValue(array, val) | |
for i = 0, #array do | |
if tostring(val) == tostring(array[i]) then | |
return i | |
end | |
end | |
return nil | |
end | |
local function getFiringPoint() | |
return script.Parent.Main.Gun.Flash.CFrame | |
end | |
local Sine = function(X) | |
return math.sin(math.rad(X)) | |
end | |
local Linear = function(X) | |
return (X / 90) | |
end | |
function numLerp(A, B, Alpha) | |
return A + (B - A) * Alpha | |
end | |
function RAND(Min, Max, Accuracy) | |
return numLerp(Min, Max, math.random()) | |
--[[local Inverse = 1 / (Accuracy or 1) | |
return (math.random(Min * Inverse, Max * Inverse) / Inverse)]] | |
end | |
function Map(Val, fromLow, fromHigh, toLow, toHigh) | |
return (Val - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) + toLow | |
end | |
local function getYawPitch(Cf) | |
local LV = Cf.lookVector | |
local Yaw = math.atan2(LV.x, -LV.z) | |
local Pitch = math.atan2(LV.y, -LV.z) | |
return Pitch, Yaw | |
end | |
local Monster = {} -- Create the monster class | |
local Enemies = {} | |
function setTurretDirection(mode, elevation, rotation) | |
--parts.MantletBase.MainGunWeld.C1 = CFrame.new(0,0,0) * CFrame.fromEulerAnglesXYZ(elevation, 0, 0); | |
--tweenJoint(parts.MantletBase.MainGunWeld,nil,CFrame.new(0,0,0) * CFrame.Angles(0, 0, elevation),Sine,0.8) | |
if mode == "MainCannon" then | |
tweenJoint(parts.TurretRing2.TurretRingWeld,nil,CFrame.Angles(0, math.clamp(rotation,-0.5 * math.pi,0.5 * math.pi) , 0),Sine,0.8) | |
elseif mode == "MGTurret" then | |
tweenJoint(Tank.Turret.Parts.TurretRing2.TurretRingWeld,nil,CFrame.Angles(0, rotation, 0),Sine,0.2) | |
tweenJoint(Tank.Turret.Parts.MantletBase.MainGunWeld,nil,CFrame.Angles(elevation, 0, 0),Sine,0.2) | |
elseif mode == "MGTurret2" then | |
tweenJoint(Tank.Turret2.Parts.TurretRing2.TurretRingWeld,nil,CFrame.Angles(0, rotation, 0),Sine,0.8) | |
tweenJoint(Tank.Turret2.Parts.MantletBase.MainGunWeld,nil,CFrame.Angles(elevation, 0, 0),Sine,0.8) | |
elseif mode == "MGTurret3" then | |
tweenJoint(Tank.Turret3.Parts.TurretRing2.TurretRingWeld,nil,CFrame.Angles(0, rotation, 0),Sine,0.8) | |
tweenJoint(Tank.Turret3.Parts.MantletBase.MainGunWeld,nil,CFrame.Angles(elevation, 0, 0),Sine,0.8) | |
elseif mode == "MGTurret4" then | |
tweenJoint(Tank.Turret4.Parts.TurretRing2.TurretRingWeld,nil,CFrame.Angles(0, rotation, 0),Sine,0.8) | |
tweenJoint(Tank.Turret4.Parts.MantletBase.MainGunWeld,nil,CFrame.Angles(elevation, 0, 0),Sine,0.8) | |
end | |
end | |
function tweenJoint(Joint, newC0, newC1, Alpha, Duration) | |
spawn(function() | |
local newCode = math.random(-1e9, 1e9) --This creates a random code between -1000000000 and 1000000000 | |
local tweenIndicator = nil | |
if (not Joint:findFirstChild("tweenCode")) then --If the joint isn't being tweened, then | |
tweenIndicator = Instance.new("IntValue") | |
tweenIndicator.Name = "tweenCode" | |
tweenIndicator.Value = newCode | |
tweenIndicator.Parent = Joint | |
else | |
tweenIndicator = Joint.tweenCode | |
tweenIndicator.Value = newCode --If the joint is already being tweened, this will change the code, and the tween loop will stop | |
end | |
--local tweenIndicator = createTweenIndicator:InvokeServer(Joint, newCode) | |
if Duration <= 0 then --If the duration is less than or equal to 0 then there's no need for a tweening loop | |
if newC0 then Joint.C0 = newC0 end | |
if newC1 then Joint.C1 = newC1 end | |
else | |
local startC0 = Joint.C0 | |
local startC1 = Joint.C1 | |
local t0 = tick() | |
while true do | |
RS.Heartbeat:wait() --This makes the for loop step every 1/60th of a second | |
local X = math.min((tick() - t0) / Duration, 1) * 90 | |
if tweenIndicator.Value ~= newCode then break end --This makes sure that another tween wasn't called on the same joint | |
if newC0 then Joint.C0 = startC0:lerp(newC0, Alpha(X)) end | |
if newC1 then Joint.C1 = startC1:lerp(newC1, Alpha(X)) end | |
--if newC0 then lerpCF:InvokeServer(Joint, "C0", startC0, newC0, Alpha(X)) end | |
--if newC1 then lerpCF:InvokeServer(Joint, "C1", startC1, newC1, Alpha(X)) end | |
if X == 90 then break end | |
end | |
end | |
if tweenIndicator.Value == newCode then --If this tween functions was the last one called on a joint then it will remove the code | |
tweenIndicator:Destroy() | |
end | |
--deleteTweenIndicator:InvokeServer(tweenIndicator, newCode) | |
end) | |
end | |
local function isEnemy(Human) | |
local Plyr2 = game.Players:GetPlayerFromCharacter(Human.Parent) | |
if (not Plyr2) then | |
if Settings.CanDamageNPCs then | |
if Human.Parent:FindFirstChild("BOT") then | |
return (require(Human.Parent.BOT).Allegiance ~= Bot.Allegiance) | |
end | |
end | |
end | |
return Settings.AllowFriendlyFire or (Plyr2 ~= nil and (Plyr2.Allegiance.Value ~= Bot.Allegiance or Plyr2.Neutral)) | |
end | |
function Monster:GetMaximumDetectionDistance() | |
-- Returns the maximum detection distance | |
local setting = Bot.ChaseRange | |
if setting < 0 then | |
return HUGE | |
else | |
return setting | |
end | |
end | |
function Monster:GetCFrame(mode,...) | |
local args = {...} | |
if mode == "MainCannon" then | |
return Tank.Main.Gun.Flash.CFrame | |
elseif mode == "MGTurret" then | |
return Tank.Turret.Gun:FindFirstChild("Flash".. args[1]).CFrame | |
elseif mode == "MGTurret2" then | |
return Tank.Turret2.Gun:FindFirstChild("Flash".. args[1]).CFrame | |
elseif mode == "MGTurret3" then | |
return Tank.Turret3.Gun:FindFirstChild("Flash".. args[1]).CFrame | |
elseif mode == "MGTurret4" then | |
return Tank.Turret4.Gun:FindFirstChild("Flash".. args[1]).CFrame | |
elseif mode == "Overall" then | |
return Tank.Main.Parts.Engine.CFrame | |
end | |
end | |
function Monster:TargetIsValid() | |
local targetHumanoid = Mind.CurrentTargetHumanoid.Value | |
if targetHumanoid and targetHumanoid:IsA 'Humanoid' and not targetHumanoid:IsDescendantOf(workspace.CorpseIgnore) and targetHumanoid.Parent then | |
return true | |
else | |
return false | |
end | |
end | |
function Monster:GetTargetCFrame() | |
local targetHumanoid = Mind.CurrentTargetHumanoid.Value | |
if Monster:TargetIsValid() then | |
if targetHumanoid.Parent.PrimaryPart then | |
return targetHumanoid.Parent.PrimaryPart.CFrame | |
else | |
return CF() | |
end | |
else | |
return CF() | |
end | |
end | |
function Monster:HasClearLineOfSight(mode,...) | |
-- Going to cast a ray to see if I can just see my target | |
local args = {...} | |
local myPos, targetPos = Monster:GetCFrame(mode,args[1]).p, Monster:GetTargetCFrame().p | |
local hit, pos = RayCast(workspace, | |
RAY( | |
myPos, | |
Monster:GetCFrame(mode,args[1]).lookVector * 300 | |
), | |
{ | |
Tank | |
} | |
) | |
return hit ~= nil and hit:IsDescendantOf(Mind.CurrentTargetHumanoid.Value.Parent) | |
end | |
local function fireAtTarget(mode,pointModifier,origin) | |
if mode == "MainCannon" then | |
spawn(function() | |
for _, item in pairs(script.Parent.Main.Gun.Flash:GetChildren()) do | |
if item.Name:find("FlashFX") then | |
item.Enabled = true | |
end | |
end | |
end) | |
script.Parent.Main.Gun.Muzzle.Sound:Play() | |
local bolt = Instance.new("Part") | |
bolt.Name = "TankBolt" | |
bolt.BrickColor = Settings.boltSettings.Color | |
bolt.Size = Settings.mainCannonBoltSettings.Size | |
bolt.Material = Enum.Material.Neon | |
bolt.CFrame = origin | |
bolt.Anchored = true | |
bolt.CanCollide = false | |
local BF = Instance.new("BodyForce") | |
BF.force = Vector3.new(0, bolt:GetMass() * (196.2 - 196.2), 0) | |
BF.Parent = bolt | |
bolt.Velocity = bolt.CFrame.lookVector * Settings.mainCannonBoltSettings.Velocity | |
bolt.Anchored = false | |
bolt.Parent = workspace | |
bolt.Touched:connect(function(hit) | |
if hit:IsDescendantOf(script.Parent) then return end | |
local exp = Instance.new("Explosion") | |
exp.BlastPressure =1000 | |
exp.DestroyJointRadiusPercent = 0 | |
exp.BlastRadius = 10; | |
exp.ExplosionType = Enum.ExplosionType.NoCraters | |
local ray =RAY(bolt.CFrame.p,(hit.CFrame.p - bolt.CFrame.p).unit * 50) | |
local h,p,n = RayCast(workspace,ray,{Tank}) | |
exp.Position = p | |
exp.Parent = workspace | |
exp.Hit:connect(function(hit,dist) | |
if hit == bolt then return end | |
Damage(hit,hit.CFrame.p,(hit.CFrame.p - p).unit,bolt.CFrame.lookVector,dist + (p - getFiringPoint().p).magnitude,{script.Parent}) | |
end) | |
end) | |
delay(1 / 4, function() | |
for _, item in pairs(script.Parent.Main.Gun.Flash:GetChildren()) do | |
if item.Name:find("FlashFX") then | |
item.Enabled = false | |
end | |
end | |
end) | |
wait(0.5) | |
elseif mode == "MGTurret" then | |
local point = Tank.Turret.Gun:FindFirstChild("Flash"..pointModifier) | |
spawn(function() | |
for _, item in pairs(point:GetChildren()) do | |
if item.Name:find("FlashFX") then | |
item.Enabled = true | |
end | |
end | |
end) | |
Tank.Turret.Gun:FindFirstChild("Muzzle" .. pointModifier).Sound:Play() | |
local bolt = Instance.new("Part") | |
bolt.Name = "TankBolt" | |
bolt.Size = Settings.mainCannonBoltSettings.Size / 2 | |
bolt.Material = Enum.Material.Neon | |
bolt.CFrame = point.CFrame | |
bolt.BrickColor = Settings.boltSettings.Color | |
bolt.Anchored = true | |
bolt.CanCollide = false | |
local BF = Instance.new("BodyForce") | |
BF.force = Vector3.new(0, bolt:GetMass() * (196.2 - 0.2), 0) | |
BF.Parent = bolt | |
bolt.Velocity = bolt.CFrame.lookVector * Settings.mainCannonBoltSettings.Velocity | |
bolt.Anchored = false | |
bolt.Parent = workspace | |
bolt.Touched:connect(function(hit) | |
if hit:IsDescendantOf(script.Parent) then return end | |
if hit == bolt then return end | |
Damage(hit,hit.CFrame.p,(hit.CFrame.p - point.Position).unit,bolt.CFrame.lookVector,(hit.CFrame.p - point.CFrame.p).magnitude,{Tank}) | |
end) | |
delay(1 / 4, function() | |
for _, item in pairs(point:GetChildren()) do | |
if item.Name:find("FlashFX") then | |
item.Enabled = false | |
end | |
end | |
end) | |
wait(60 / Settings.MGRPM) | |
elseif mode == "MGTurret2" then | |
local point = Tank.Turret2.Gun:FindFirstChild("Flash"..pointModifier) | |
spawn(function() | |
for _, item in pairs(point:GetChildren()) do | |
if item.Name:find("FlashFX") then | |
item.Enabled = true | |
end | |
end | |
end) | |
Tank.Turret2.Gun:FindFirstChild("Muzzle" .. pointModifier).Sound:Play() | |
local bolt = Instance.new("Part") | |
bolt.Name = "TankBolt" | |
bolt.Size = Settings.mainCannonBoltSettings.Size / 2 | |
bolt.Material = Enum.Material.Neon | |
bolt.CFrame = point.CFrame | |
bolt.Anchored = true | |
bolt.CanCollide = false | |
local BF = Instance.new("BodyForce") | |
BF.force = Vector3.new(0, bolt:GetMass() * (196.2 - 0.2), 0) | |
BF.Parent = bolt | |
bolt.BrickColor = Settings.boltSettings.Color | |
bolt.Velocity = bolt.CFrame.lookVector * Settings.mainCannonBoltSettings.Velocity | |
bolt.Anchored = false | |
bolt.Parent = workspace | |
bolt.Touched:connect(function(hit) | |
if hit:IsDescendantOf(script.Parent) then return end | |
if hit == bolt then return end | |
Damage(hit,hit.CFrame.p,(hit.CFrame.p - point.Position).unit,bolt.CFrame.lookVector,(hit.CFrame.p - point.CFrame.p).magnitude,{Tank}) | |
end) | |
delay(1 / 4, function() | |
for _, item in pairs(point:GetChildren()) do | |
if item.Name:find("FlashFX") then | |
item.Enabled = false | |
end | |
end | |
end) | |
wait(60 / Settings.MGRPM) | |
elseif mode == "MGTurret3" then | |
local point = Tank.Turret3.Gun:FindFirstChild("Flash"..pointModifier) | |
spawn(function() | |
for _, item in pairs(point:GetChildren()) do | |
if item.Name:find("FlashFX") then | |
item.Enabled = true | |
end | |
end | |
end) | |
Tank.Turret3.Gun:FindFirstChild("Muzzle" .. pointModifier).Sound:Play() | |
local bolt = Instance.new("Part") | |
bolt.Name = "TankBolt" | |
bolt.Size = Settings.mainCannonBoltSettings.Size / 2 | |
bolt.Material = Enum.Material.Neon | |
bolt.CFrame = point.CFrame | |
bolt.Anchored = true | |
bolt.CanCollide = false | |
bolt.BrickColor = Settings.boltSettings.Color | |
local BF = Instance.new("BodyForce") | |
BF.force = Vector3.new(0, bolt:GetMass() * (196.2 - 0.2), 0) | |
BF.Parent = bolt | |
bolt.Velocity = bolt.CFrame.lookVector * Settings.mainCannonBoltSettings.Velocity | |
bolt.Anchored = false | |
bolt.Parent = workspace | |
bolt.Touched:connect(function(hit) | |
if hit:IsDescendantOf(script.Parent) then return end | |
if hit == bolt then return end | |
Damage(hit,hit.CFrame.p,(hit.CFrame.p - point.Position).unit,bolt.CFrame.lookVector,(hit.CFrame.p - point.CFrame.p).magnitude,{Tank}) | |
end) | |
delay(1 / 4, function() | |
for _, item in pairs(point:GetChildren()) do | |
if item.Name:find("FlashFX") then | |
item.Enabled = false | |
end | |
end | |
end) | |
wait(60 / Settings.MGRPM) | |
elseif mode == "MGTurret4" then | |
local point = Tank.Turret4.Gun:FindFirstChild("Flash"..pointModifier) | |
spawn(function() | |
for _, item in pairs(point:GetChildren()) do | |
if item.Name:find("FlashFX") then | |
item.Enabled = true | |
end | |
end | |
end) | |
Tank.Turret4.Gun:FindFirstChild("Muzzle" .. pointModifier).Sound:Play() | |
local bolt = Instance.new("Part") | |
bolt.Name = "TankBolt" | |
bolt.Size = Settings.mainCannonBoltSettings.Size / 2 | |
bolt.Material = Enum.Material.Neon | |
bolt.CFrame = point.CFrame | |
bolt.Anchored = true | |
bolt.CanCollide = false | |
bolt.BrickColor = Settings.boltSettings.Color | |
local BF = Instance.new("BodyForce") | |
BF.force = Vector3.new(0, bolt:GetMass() * (196.2 - 0.2), 0) | |
BF.Parent = bolt | |
bolt.Velocity = bolt.CFrame.lookVector * Settings.mainCannonBoltSettings.Velocity | |
bolt.Anchored = false | |
bolt.Parent = workspace | |
bolt.Touched:connect(function(hit) | |
if hit:IsDescendantOf(script.Parent) then return end | |
if hit == bolt then return end | |
Damage(hit,hit.CFrame.p,(hit.CFrame.p - point.Position).unit,bolt.CFrame.lookVector,(hit.CFrame.p - point.CFrame.p).magnitude,{Tank}) | |
end) | |
delay(1 / 4, function() | |
for _, item in pairs(point:GetChildren()) do | |
if item.Name:find("FlashFX") then | |
item.Enabled = false | |
end | |
end | |
end) | |
wait(60 / Settings.MGRPM) | |
end | |
end | |
function getBaseDamage(Dist) | |
local startDmg = Settings.damageSettings.Start.Damage | |
local startDist = Settings.damageSettings.Start.Dist | |
local endDmg = Settings.damageSettings.End.Damage | |
local endDist = Settings.damageSettings.End.Dist | |
return ( | |
( | |
Dist < startDist * Settings.mainCannonBoltSettings.Range | |
) and startDmg or | |
( | |
Dist >= startDist * Settings.mainCannonBoltSettings.Range and | |
Dist < endDist * Settings.mainCannonBoltSettings.Range | |
) and numLerp(startDmg, endDmg, Map(Dist / Settings.mainCannonBoltSettings.Range, startDist, endDist, 0, 1)) or | |
( | |
Dist >= endDist * Settings.mainCannonBoltSettings.Range | |
) and endDmg | |
) | |
end | |
function Damage(H, P, N, D, Dist, customIgnore) | |
local hVal = Settings.damageSettings.Multipliers.Head | |
local cVal = Settings.damageSettings.Multipliers.Chest | |
local lVal = Settings.damageSettings.Multipliers.Limbs | |
local baseDamage = getBaseDamage(Dist) | |
if script.Parent.Human.Health.Value ~= 0 then | |
local hitHumanoid = nil | |
if H.Parent:IsA("Hat") then | |
table.insert(customIgnore, H) | |
local newRay = Ray.new(P - D * 0.1, D * (Settings.mainCannonBoltSettings.Range - Dist + 0.1)) | |
local newH, newP, newN = workspace:FindPartOnRayWithIgnoreList(newRay, customIgnore) | |
if newH then | |
hitHumanoid = Damage(newH, newP, newN, D, Dist + (newP - P).magnitude, customIgnore) | |
end | |
else | |
hitHumanoid = H.Parent:FindFirstChildOfClass("Humanoid") | |
if hitHumanoid and hitHumanoid.Health > 0 and isEnemy(hitHumanoid) then | |
local chosenDamage = 0 | |
if H.Name == "Head" then | |
chosenDamage = baseDamage * RAND(hVal, hVal + 0.1, 0.01) | |
elseif H.Name == "Torso" then | |
chosenDamage = baseDamage * RAND(cVal, cVal + 0.1, 0.01) | |
else | |
chosenDamage = baseDamage * RAND(lVal, lVal + 0.1, 0.01) | |
end | |
tagHumanoid(hitHumanoid,chosenDamage) | |
hitHumanoid:TakeDamage(chosenDamage) | |
end | |
end | |
return hitHumanoid | |
end | |
end | |
function Monster:GetClosestEnemies() | |
local result = {} | |
local enemyAIs = workspace.Mobs:GetChildren() | |
local Tanks = workspace.Tanks:GetChildren() | |
local enemyPlayers = bindableService.fetch("PlayerList") | |
for i, enemy in next, enemyAIs, nil do | |
if enemy then | |
if enemy:FindFirstChildOfClass("Humanoid") then | |
if require(enemy.BOT).Allegiance ~= Bot.Allegiance and enemy.PrimaryPart then | |
local distance = (enemy.PrimaryPart.CFrame.p - Monster:GetCFrame("Overall").p).magnitude | |
if distance < Monster:GetMaximumDetectionDistance() then | |
result[#result+1] = enemy | |
end | |
end | |
end | |
end | |
end | |
for i, enemy in next, Tanks, nil do | |
if enemy then | |
if enemy:FindFirstChild("Human") then | |
if require(enemy.BOT).Allegiance ~= Bot.Allegiance and enemy.PrimaryPart then | |
local distance = (enemy.PrimaryPart.CFrame.p - Monster:GetCFrame("Overall").p).magnitude | |
if distance < Monster:GetMaximumDetectionDistance() then | |
result[#result+1] = enemy | |
end | |
end | |
end | |
end | |
end | |
for i, enemy in next, enemyPlayers, nil do | |
if enemy then | |
if enemy.Character then | |
if enemy.Character:FindFirstChildOfClass("Humanoid") then | |
if enemy.Allegiance.Value ~= Bot.Allegiance then | |
local distance = (enemy.Character.PrimaryPart.CFrame.p - Monster:GetCFrame("Overall").p).magnitude | |
if distance < Monster:GetMaximumDetectionDistance() then | |
local squadMates = enemy.playerArmy.Value:GetChildren() | |
for j, secondEnemy in next, squadMates, nil do | |
if secondEnemy:FindFirstChildOfClass("Humanoid") and secondEnemy.PrimaryPart then | |
local distance = (secondEnemy.PrimaryPart.CFrame.p - Monster:GetCFrame("Overall").p).magnitude | |
if distance < Monster:GetMaximumDetectionDistance() then | |
result[#result+1] = secondEnemy | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
return result | |
end | |
function Monster:SearchForTarget(randomized) | |
-- Finds the closest player and sets the target | |
local npcs = Monster:GetClosestEnemies() | |
local closestCharacter, closestCharacterDistance | |
if not randomized then | |
for i, npc in next, npcs, nil do | |
local npcBOT = require(npc.BOT) | |
if npcBOT.Allegiance ~= Bot.Allegiance then | |
if npc ~= nil and npc:FindFirstChild('Human') ~= nil and npc.Human:IsA('Humanoid') then | |
local distance = (npc.PrimaryPart.CFrame.p - Monster:GetCFrame("Overall").p).magnitude | |
if distance < Monster:GetMaximumDetectionDistance() then | |
if closestCharacter == nil then | |
closestCharacter, closestCharacterDistance = npc, distance | |
else | |
if closestCharacterDistance > distance then | |
closestCharacter, closestCharacterDistance = npc, distance | |
Data.EnemyAllegiance = npcBOT.Allegiance | |
end | |
end | |
end | |
end | |
end | |
end | |
local players = bindableService.fetch("PlayerList") | |
for i, player in next, players, nil do | |
if player.Allegiance.Value ~= Bot.Allegiance then | |
local character = player.Character | |
if character ~= nil and character:FindFirstChild('Humanoid') ~= nil and character.Humanoid:IsA('Humanoid') then | |
local distance = (character.PrimaryPart.CFrame.p - Monster:GetCFrame("Overall").p).magnitude | |
if distance < Monster:GetMaximumDetectionDistance() then | |
if closestCharacter == nil then | |
closestCharacter, closestCharacterDistance = character, distance | |
else | |
if closestCharacterDistance > distance then | |
closestCharacter, closestCharacterDistance = character, distance | |
Data.EnemyAllegiance = player.Allegiance.Value | |
end | |
end | |
end | |
end | |
end | |
end | |
else | |
closestCharacter = npcs[math.random(1,#npcs)] | |
end | |
if closestCharacter ~= nil then | |
return closestCharacter | |
else | |
return nil | |
end | |
end | |
function Monster:Update() | |
local enemy = Monster:SearchForTarget(false) | |
if enemy then | |
if enemy:IsA("Model") then | |
if (Monster:GetTargetCFrame().p - Monster:GetCFrame("Overall").p).magnitude <= 2048 then | |
Mind.CurrentTargetHumanoid.Value = enemy:FindFirstChild("Human") | |
if not Monster:TargetIsValid() then return end | |
local gunModifier = math.random(1,5) | |
local pointModifier = math.random(1,2) | |
if gunModifier == 1 then | |
setTurretDirection("MainCannon",getYawPitch(CFrame.new(parts.GunBase.CFrame.p,Monster:GetTargetCFrame().p))) | |
Engine.BodyVelocity.Velocity = Engine.CFrame.lookVector * 25 | |
Engine.BodyGyro.CFrame = CFrame.new(Engine.CFrame.p,Engine.CFrame.p + (Monster:GetTargetCFrame().p - Engine.CFrame.p).unit * Vector3.new(1,0,1)) | |
setTurretDirection("MainCannon",getYawPitch(CFrame.new(parts.GunBase.CFrame.p,parts.GunBase.CFrame.p + (Monster:GetTargetCFrame().p - parts.GunBase.CFrame.p).unit))) | |
fireAtTarget("MainCannon",pointModifier,getFiringPoint()) | |
elseif gunModifier == 2 then | |
setTurretDirection("MGTurret",getYawPitch(CFrame.new(Tank.Turret.Parts.GunBase.CFrame.p,Monster:GetTargetCFrame().p))) | |
Engine.BodyVelocity.Velocity = Engine.CFrame.lookVector * 25 | |
Engine.BodyGyro.CFrame = CFrame.new(Engine.CFrame.p,Engine.CFrame.p + (Monster:GetTargetCFrame().p - Engine.CFrame.p).unit * Vector3.new(1,0,1)) | |
setTurretDirection("MGTurret",getYawPitch(CFrame.new(Tank.Turret.Parts.GunBase.CFrame.p,Tank.Turret.Parts.GunBase.CFrame.p + (Monster:GetTargetCFrame().p - Tank.Turret.Parts.GunBase.CFrame.p).unit))) | |
fireAtTarget("MGTurret",pointModifier,getFiringPoint()) | |
elseif gunModifier == 3 then | |
setTurretDirection("MGTurret2",getYawPitch(CFrame.new(Tank.Turret2.Parts.GunBase.CFrame.p,Monster:GetTargetCFrame().p))) | |
Engine.BodyVelocity.Velocity = Engine.CFrame.lookVector * 25 | |
Engine.BodyGyro.CFrame = CFrame.new(Engine.CFrame.p,Engine.CFrame.p + (Monster:GetTargetCFrame().p - Engine.CFrame.p).unit * Vector3.new(1,0,1)) | |
setTurretDirection("MGTurret2",getYawPitch(CFrame.new(Tank.Turret2.Parts.GunBase.CFrame.p,Tank.Turret2.Parts.GunBase.CFrame.p + (Monster:GetTargetCFrame().p - Tank.Turret2.Parts.GunBase.CFrame.p).unit))) | |
fireAtTarget("MGTurret2",pointModifier,getFiringPoint()) | |
elseif gunModifier == 4 then | |
setTurretDirection("MGTurret3",getYawPitch(CFrame.new(Tank.Turret3.Parts.GunBase.CFrame.p,Monster:GetTargetCFrame().p))) | |
Engine.BodyVelocity.Velocity = Engine.CFrame.lookVector * 25 | |
Engine.BodyGyro.CFrame = CFrame.new(Engine.CFrame.p,Engine.CFrame.p + (Monster:GetTargetCFrame().p - Engine.CFrame.p).unit * Vector3.new(1,0,1)) | |
setTurretDirection("MGTurret3",getYawPitch(CFrame.new(Tank.Turret3.Parts.GunBase.CFrame.p,Tank.Turret3.Parts.GunBase.CFrame.p + (Monster:GetTargetCFrame().p - Tank.Turret3.Parts.GunBase.CFrame.p).unit))) | |
fireAtTarget("MGTurret3",pointModifier,getFiringPoint()) | |
elseif gunModifier == 5 then | |
setTurretDirection("MGTurret4",getYawPitch(CFrame.new(Tank.Turret4.Parts.GunBase.CFrame.p,Monster:GetTargetCFrame().p))) | |
Engine.BodyVelocity.Velocity = Engine.CFrame.lookVector * 25 | |
Engine.BodyGyro.CFrame = CFrame.new(Engine.CFrame.p,Engine.CFrame.p + (Monster:GetTargetCFrame().p - Engine.CFrame.p).unit * Vector3.new(1,0,1)) | |
setTurretDirection("MGTurret4",getYawPitch(CFrame.new(Tank.Turret4.Parts.GunBase.CFrame.p,Tank.Turret4.Parts.GunBase.CFrame.p + (Monster:GetTargetCFrame().p - Tank.Turret4.Parts.GunBase.CFrame.p).unit))) | |
fireAtTarget("MGTurret4",pointModifier,getFiringPoint()) | |
end | |
end | |
elseif game.Players:GetPlayerFromCharacter(enemy) then | |
local player = game.Players:GetPlayerFromCharacter(enemy) | |
if player then | |
if player:DistanceFromCharacter(Engine.Position).magnitude <= 2048 then | |
Mind.CurrentTargetHumanoid.Value = enemy.Humanoid | |
local gunModifier = math.random(1,5) | |
local pointModifier = math.random(1,2) | |
if gunModifier == 1 then | |
setTurretDirection("MainCannon",getYawPitch(CFrame.new(parts.GunBase.CFrame.p,Monster:GetTargetCFrame().p))) | |
Engine.BodyVelocity.Velocity = Engine.CFrame.lookVector * 25 | |
Engine.BodyGyro.CFrame = CFrame.new(Engine.CFrame.p,Engine.CFrame.p + (Monster:GetTargetCFrame().p - Engine.CFrame.p).unit * Vector3.new(1,0,1)) | |
setTurretDirection("MainCannon",getYawPitch(CFrame.new(parts.GunBase.CFrame.p,parts.GunBase.CFrame.p + (Monster:GetTargetCFrame().p - parts.GunBase.CFrame.p).unit))) | |
fireAtTarget("MainCannon",pointModifier,getFiringPoint()) | |
elseif gunModifier == 2 then | |
setTurretDirection("MGTurret",getYawPitch(CFrame.new(Tank.Turret.Parts.GunBase.CFrame.p,Monster:GetTargetCFrame().p))) | |
Engine.BodyVelocity.Velocity = Engine.CFrame.lookVector * 25 | |
Engine.BodyGyro.CFrame = CFrame.new(Engine.CFrame.p,Engine.CFrame.p + (Monster:GetTargetCFrame().p - Engine.CFrame.p).unit * Vector3.new(1,0,1)) | |
setTurretDirection("MGTurret",getYawPitch(CFrame.new(Tank.Turret.Parts.GunBase.CFrame.p,Tank.Turret.Parts.GunBase.CFrame.p + (Monster:GetTargetCFrame().p - Tank.Turret.Parts.GunBase.CFrame.p).unit))) | |
fireAtTarget("MGTurret",pointModifier,getFiringPoint()) | |
elseif gunModifier == 3 then | |
setTurretDirection("MGTurret2",getYawPitch(CFrame.new(Tank.Turret2.Parts.GunBase.CFrame.p,Monster:GetTargetCFrame().p))) | |
Engine.BodyVelocity.Velocity = Engine.CFrame.lookVector * 25 | |
Engine.BodyGyro.CFrame = CFrame.new(Engine.CFrame.p,Engine.CFrame.p + (Monster:GetTargetCFrame().p - Engine.CFrame.p).unit * Vector3.new(1,0,1)) | |
setTurretDirection("MGTurret2",getYawPitch(CFrame.new(Tank.Turret2.Parts.GunBase.CFrame.p,Tank.Turret2.Parts.GunBase.CFrame.p + (Monster:GetTargetCFrame().p - Tank.Turret2.Parts.GunBase.CFrame.p).unit))) | |
fireAtTarget("MGTurret2",pointModifier,getFiringPoint()) | |
elseif gunModifier == 4 then | |
setTurretDirection("MGTurret3",getYawPitch(CFrame.new(Tank.Turret3.Parts.GunBase.CFrame.p,Monster:GetTargetCFrame().p))) | |
Engine.BodyVelocity.Velocity = Engine.CFrame.lookVector * 25 | |
Engine.BodyGyro.CFrame = CFrame.new(Engine.CFrame.p,Engine.CFrame.p + (Monster:GetTargetCFrame().p - Engine.CFrame.p).unit * Vector3.new(1,0,1)) | |
setTurretDirection("MGTurret3",getYawPitch(CFrame.new(Tank.Turret3.Parts.GunBase.CFrame.p,Tank.Turret3.Parts.GunBase.CFrame.p + (Monster:GetTargetCFrame().p - Tank.Turret3.Parts.GunBase.CFrame.p).unit))) | |
fireAtTarget("MGTurret3",pointModifier,getFiringPoint()) | |
elseif gunModifier == 5 then | |
setTurretDirection("MGTurret4",getYawPitch(CFrame.new(Tank.Turret4.Parts.GunBase.CFrame.p,Monster:GetTargetCFrame().p))) | |
Engine.BodyVelocity.Velocity = Engine.CFrame.lookVector * 25 | |
Engine.BodyGyro.CFrame = CFrame.new(Engine.CFrame.p,Engine.CFrame.p + (Monster:GetTargetCFrame().p - Engine.CFrame.p).unit * Vector3.new(1,0,1)) | |
setTurretDirection("MGTurret4",getYawPitch(CFrame.new(Tank.Turret4.Parts.GunBase.CFrame.p,Tank.Turret4.Parts.GunBase.CFrame.p + (Monster:GetTargetCFrame().p - Tank.Turret4.Parts.GunBase.CFrame.p).unit))) | |
fireAtTarget("MGTurret4",pointModifier,getFiringPoint()) | |
end | |
end | |
end | |
end | |
wait(16) | |
Mind.CurrentTargetHumanoid.Value = nil | |
else | |
local points = game.Workspace.TankPatrolPoints:GetChildren() | |
local point = points[#points].CFrame.p | |
Engine.BodyGyro.CFrame = CFrame.new(Engine.CFrame.p,Engine.CFrame.p + (point - Engine.CFrame.p).unit * Vector3.new(1,0,1)) | |
Engine.BodyVelocity.Velocity = Engine.CFrame.lookVector * 25 | |
repeat wait() until (point - Engine.CFrame.p).magnitude <= 3 | |
end | |
end | |
spawn(function() | |
for _, hullPart in pairs(script.Parent.Main.Hull:GetChildren()) do | |
hullPart.Touched:connect(function(hit) | |
Damage(hit,hit.CFrame.p,(hit.CFrame.p - Engine.Position).unit,Engine.CFrame.lookVector,(Engine.Position - getFiringPoint().p).magnitude,{script.Parent}) | |
end) | |
end | |
end) | |
Tank.DescendantRemoving:connect(function(item) | |
if item:IsA("JointInstance") then | |
Tank.Human.Health.Value = 0 | |
end | |
end) | |
Engine.Start:Play() | |
wait(1) | |
Engine.Loop:Play() | |
spawn(function() | |
while wait() do | |
if Engine.CFrame.p.Y > -130 then | |
Engine.BodyPosition.MaxForce = Vector3.new(0,40000000,0) | |
Engine.BodyPosition.Position = Vector3.new(Engine.CFrame.p.X,-130,Engine.CFrame.p.Z) | |
else | |
Engine.BodyPosition.MaxForce = Vector3.new(0,0,0) | |
end | |
end | |
end) | |
script.Parent.Human.Health.Changed:connect(function(health) | |
if health <= 0 then | |
local Humanoid = script.Parent:FindFirstChild("Human") | |
local xp = 40 | |
local gold = 0 | |
local people = {} | |
local damages = {} | |
local weapons = {} | |
for _, tagStr in pairs(game:GetService("CollectionService"):GetTags(Humanoid)) do | |
local tag = DamageTag.ParseTag(tagStr) | |
if tag then | |
local Killer = tag:GetKiller() | |
local usedWeapon = tag:GetWeaponName() | |
if Killer then | |
if not isInPeople(people, Killer) then | |
people[#people+1] = Killer | |
weapons[#weapons+1] = usedWeapon | |
damages[#damages+1] = tag.dmg | |
else | |
if string.lower(Others.XPShareMode) ~= "classic" then | |
local y = getIndexOfValue(people, Killer) | |
damages[y] = damages[y] + CEIL(tag.dmg) | |
end | |
end | |
end | |
end | |
RS.Heartbeat:wait() | |
end | |
local health = 0 | |
for i,v in pairs(damages) do | |
health = health + v | |
end | |
table.sort(people,function(a,b) | |
local damagea, damageb | |
local indexA, indexB = getIndexOfValue(people,a), getIndexOfValue(people,b) | |
damagea = damages[indexA] | |
damageb = damages[indexB] | |
return damagea > damageb | |
end) | |
table.sort(damages,function(a,b) | |
return a > b | |
end) | |
table.sort(weapons,function(a,b) | |
local damagea, damageb | |
local indexA, indexB = getIndexOfValue(weapons,a), getIndexOfValue(weapons,b) | |
damagea = damages[indexA] | |
damageb = damages[indexB] | |
return damagea > damageb | |
end) | |
spawn(function() | |
local prevV = nil | |
for d, v in pairs(people) do | |
print("Giving stats to ", v.Name, " | ", d) | |
if v ~= nil then | |
if prevV ~= v then | |
prevV = v | |
if v:IsA("Player") then | |
local ls = v:FindFirstChild("leaderstats") | |
if ls then | |
if d == 1 then | |
ProgressionService:AddXP(v, (damages[d]/health)*xp, "tank") | |
elseif d > 1 and d <= 3 then | |
ProgressionService:AddXP(v, (damages[d]/health)*xp, "tankassist_kill") | |
else | |
ProgressionService:AddXP(v, (damages[d]/health)*xp, "tank_assist") | |
end | |
--Module:AwardPlayerPoints(CEIL((damages[d]/health)*xp), v) | |
end | |
end | |
end | |
end | |
RS.Heartbeat:wait() | |
end | |
end) | |
local exp = Instance.new("Explosion") | |
exp.Position = Engine.Position | |
exp.BlastRadius = script.Parent:GetExtentsSize().magnitude | |
exp.ExplosionType = Enum.ExplosionType.NoCraters | |
exp.Parent = workspace | |
game.Debris:AddItem(script.Parent,4) | |
end | |
end) | |
while script.Parent.Human.Health.Value > 0 do | |
Monster:Update() | |
wait() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment