Advertisement
Guest User

Untitled

a guest
Sep 18th, 2019
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.46 KB | None | 0 0
  1. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  2.  
  3. local clock =           require(ReplicatedStorage.TimeSyncManager)
  4. local NG =              require(script.NameGenerator)
  5. local DecisionTree =    require(script.NPCDecisionTree)
  6.  
  7. local sin = math.sin
  8.  
  9. local NPC_IdCount = 1
  10. local NPC_Count = 0
  11.  
  12. local events = {}
  13. local folder = Instance.new("Folder")
  14.     folder.Name = "NPC_Events"
  15.     folder.Parent = ReplicatedStorage
  16.    
  17. local function registerEvent(name)
  18.     local NewNpcEvent = Instance.new("RemoteEvent")
  19.     NewNpcEvent.Name = name
  20.     NewNpcEvent.Parent = folder
  21.     events[name] = NewNpcEvent
  22.     return NewNpcEvent
  23. end
  24. registerEvent("NewNpc")
  25. registerEvent("WatchNpc")
  26.  
  27. local npcFolder = Instance.new("Folder")
  28.     npcFolder.Name = "NPCs"
  29.     npcFolder.Parent = workspace
  30.  
  31. local boidTemp = Instance.new("Part")
  32.     boidTemp.Anchored = true
  33.     boidTemp.CanCollide = false
  34.     boidTemp.Size = Vector3.new(1,2,1)
  35.     boidTemp.CFrame = CFrame.new(0,5,0)
  36.     boidTemp.TopSurface = "Smooth"
  37.     boidTemp.BottomSurface = "Smooth"
  38.     boidTemp.Material = "SmoothPlastic"
  39. local boidProperties = Instance.new("Folder")
  40.     boidProperties.Name = "Properties"
  41.     boidProperties.Parent = boidTemp
  42.    
  43.    
  44. ---------------------------------------------------------------------------------------------------------------------------------
  45.                         -- / Private Methods /--
  46. ---------------------------------------------------------------------------------------------------------------------------------
  47.  
  48.  
  49. local function RunStatChanges(self)
  50.     --print("A second has passed, updating for NPC_"..self.id)
  51.     local s = self.stats
  52.     s.stamina = s.stamina - .1
  53.     s.thirst = s.thirst < 100 and s.thirst + .25 or 100
  54.     s.hunger = s.hunger < 100 and s.hunger + .1 or 100
  55.     local t, h = s.thirst, s.hunger
  56.    
  57.     if t > 85 or h > 85 then
  58.         s.health = s.health - 1
  59.         --s.walkSpeed = 12 -- slowdown when starving
  60.     elseif h < 30 then
  61.         s.health = s.health < 100 and s.health + .5 or 100
  62.     end
  63.    
  64.     if s.health <= 0 then
  65.         -- kill npc
  66.     end
  67.    
  68.     if s.stamina <= 0 then
  69.         s.stamina = 0
  70.         --s.walkSpeed = 16
  71.     else
  72.         -- reset walkspeed?
  73.     end
  74.     --[[
  75.     for stat, val in pairs(self.stats) do
  76.         print(stat..": "..val)
  77.     end]]
  78. end
  79.  
  80.  
  81. local function BeginUpdateCycle(self)
  82.     local HB
  83.     local t = 0 -- time passed tracker
  84.     local logic = DecisionTree()
  85.     logic:setObject(self)
  86.     HB = game:GetService("RunService").Heartbeat:Connect(function(timePassed)
  87.         logic:run()
  88.        
  89.         t = t + timePassed
  90.         if t >= 1 then
  91.             t = t - 1
  92.             RunStatChanges(self)
  93.         end
  94.     end)
  95.     return HB
  96. end
  97.  
  98.  
  99. local function newBoid(id)
  100.     local b = boidTemp:Clone()
  101.     b.Name = id
  102.     b.Parent = npcFolder
  103.     return b
  104. end
  105.  
  106. local function initStats(stats)
  107.     local function newItem(Type,Value)
  108.         local obj = Instance.new(Type)
  109.         obj.Value = Value
  110.         obj.Parent = stats[2]
  111.     end
  112.     for stat, value in pairs(stats[1]) do
  113.         local t = typeof(value)
  114.         if t == "number" then
  115.             newItem("NumberValue",value)
  116.         elseif t == "boolean" then
  117.             newItem("BoolValue",value)
  118.         elseif t == "string" then
  119.             newItem("StringValue",value)
  120.         elseif t == "Instance" then
  121.             newItem("ObjectValue",value)
  122.         else
  123.             warn("Illegal Type:",t,"for property:",stat)
  124.         end
  125.     end
  126. end
  127.  
  128. ---------------------------------------------------------------------------------------------------------------------------------
  129.                         -- / Metatable Handling / --
  130. ---------------------------------------------------------------------------------------------------------------------------------
  131. local NPC = {npcs = {}}
  132. NPC.__index = NPC
  133. NPC.__tostring = function(t)
  134.     return "NPC_"..t.id..":\t"..t.firstName.." "..t.lastName.."\n\tAge: "..t.age.."\n\tSex: "..(t.sex == 1 and "Male" or "Female")
  135. end
  136.  
  137. function NPC:Init()
  138.     print("Initialized Server Side")
  139. end
  140.  
  141. local StatManager = {}
  142. StatManager.__index = function(t,k)
  143.     return t[1][k:lower()]
  144. end
  145. StatManager.__newindex = function(t,k,v)
  146.     k = k:lower()
  147.     t[1][k] = v
  148.     local prop = t[2]:FindFirstChild(k)
  149.     if prop then
  150.         prop.Value = v
  151.     end
  152. end
  153.  
  154.  
  155. ---------------------------------------------------------------------------------------------------------------------------------
  156.                         -- / Constructors / --
  157. ---------------------------------------------------------------------------------------------------------------------------------
  158.  
  159. function NPC.new()
  160.     -- Prebuild setup for multi use data
  161.     local s = math.random(1,2) -- sex: 1 is male, 2 is female
  162.  
  163.     -- put custom data here (you can erase anything in this table)
  164.     local container = setmetatable({
  165.             mom = nil,
  166.             dad = nil,
  167.             children = {},
  168.            
  169.             sex = s,
  170.             firstName = NG.NewFirstName(s),
  171.             lastName = NG.LastNames[math.random(#NG.LastNames)],
  172.             age = math.random(18,64),
  173.            
  174.             home = nil,
  175.             job = nil,
  176.     }, NPC)
  177.    
  178.     container.__index = container
  179.     container.__newindex = function(t,k,v)
  180.         t:Set(k,v)
  181.     end
  182.    
  183.     local b = newBoid(NPC_IdCount)
  184.     local self = setmetatable({
  185.         -- Core Data (Immutable)
  186.         id = NPC_IdCount,
  187.         boid = b,
  188.         event = registerEvent("UpdateRegisterNPC_"..NPC_Count),
  189.        
  190.         -- Stat Data (represented as object values) (change however you like)
  191.         stats = setmetatable({{
  192.             health = 100,
  193.             hunger = 0,
  194.             thirst = 0,
  195.             stamina = 100,
  196.             walkspeed = 10
  197.         },b.Properties},StatManager),
  198.        
  199.         -- properties to update to client
  200.         watchList = {},
  201.     }, container)
  202.    
  203.     -- Finalizations
  204.     NPC_IdCount = NPC_IdCount + 1
  205.     NPC_Count = NPC_Count + 1
  206.     initStats(self.stats)
  207.     NPC.npcs[self.boid] = self
  208.     events.NewNpc:FireAllClients(self.event,self.boid)
  209.     self.updateCycle = BeginUpdateCycle(self)
  210.    
  211.     return self
  212. end
  213.  
  214. --[[
  215. function NPC.birth(mom,dad)
  216.     local self = NPC.new()
  217.     self.mom = mom
  218.     self.dad = dad
  219.     self.age = 0
  220.     return self
  221. end]]
  222.  
  223. function NPC:CreateOnClient(plr)
  224.     events.NewNpc:FireClient(plr,self.event,self.boid)
  225. end
  226.  
  227.  
  228. ---------------------------------------------------------------------------------------------------------------------------------
  229.                         -- / Public Methods / -- (Dont mess with these)
  230. ---------------------------------------------------------------------------------------------------------------------------------
  231.  
  232. function NPC:Destroy()
  233.     NPC.npcs[self.boid] = nil
  234.     -- tell clients to destroy their copy
  235.    
  236.     self.updateCycle:Disconnect()
  237.     self.boid:Destroy()
  238.     NPC_Count = NPC_Count - 1
  239. end
  240.  
  241. -- Client manager for custom data
  242. function NPC:Set(property, newVal)
  243.    
  244. end
  245.  
  246. function NPC:Watch(plr,...)
  247.     local props = type(...) == "table" and ... or {...}
  248.    
  249. end
  250.  
  251. function NPC:StopWatching(property)
  252.    
  253. end
  254.  
  255.  
  256. function NPC:GetWalkSpeed()
  257.     return self.stats.walkSpeed - self.age/40
  258. end
  259.  
  260.  
  261. function NPC:GoTo(pos)
  262.     return self:MoveTo(pos)
  263. end
  264.  
  265.  
  266. function NPC:MoveTo(pos)
  267.     local dist = (self.boid.Position - pos).magnitude
  268.     local t = dist/self:GetWalkSpeed()
  269.     local startTime = clock:GetTime()
  270.     self.boid.CFrame = CFrame.new(pos)
  271.     self.event:FireAllClients("MoveTo", pos, startTime, startTime+t)
  272.     --print("time to complete:",t)
  273.     wait(t-.05)
  274.     return true
  275. end
  276.  
  277. ---------------------------------------------------------------------------------------------------------------------------------
  278.                         -- / Custom Public Methods / -- (Put your custom methods here)
  279. ---------------------------------------------------------------------------------------------------------------------------------
  280.  
  281. -- Optional
  282. -- Takes a string and sets the npcs name
  283. function NPC:SetName(newName)
  284.     self.firstName = newName
  285. end
  286.  
  287. -- Optional
  288. -- Ages the npc by one year
  289. function NPC:Age()
  290.     self.age = self.age + 1
  291.     return self.age
  292. end
  293.  
  294.  
  295.  
  296.  
  297. -- Module Close --
  298. return NPC
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement