Advertisement
tripono

ewq

Apr 12th, 2017
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.50 KB | None | 0 0
  1. local FF_LOCAL_ARMOR_DATA = false
  2.  
  3. while not _G.ErrorOut do wait() end
  4.  
  5. local Create = LoadLibrary('RbxUtility').Create
  6.  
  7. local IsInventoryFull = script:WaitForChild('IsInventoryFull')
  8. local GetItemCost = script:WaitForChild('GetItemCost')
  9. local QueueUpdateArmorData = script:WaitForChild('QueueUpdateArmorData')
  10.  
  11. local ModifierManager = Workspace:WaitForChild('ModifierManager')
  12. local AddModifier = ModifierManager:WaitForChild('AddModifier')
  13. local RemoveModifier = ModifierManager:WaitForChild('RemoveModifier')
  14.  
  15. -- Wait for a value of a given name to be parented to a given object,
  16. -- and for it to have a non-default value.
  17. function WaitForValueObject(parent, name, defaultValue)
  18. local obj = parent:WaitForChild(name)
  19. while obj.Value == defaultValue do obj.Changed:wait() end
  20. return obj
  21. end
  22.  
  23. -- Same as WaitForValueObject but return the value of the recieved
  24. -- object rather than the object itself.
  25. function WaitForValueObjectValue(parent, name, defaultValue)
  26. return WaitForValueObject(parent, name, defaultValue).Value
  27. end
  28.  
  29. -- Info about pagination for GUIs
  30. local PAGE_WIDTH = 4
  31. local PAGE_HEIGHT = 4
  32. local TMP_PAGE_COUNT = 1
  33.  
  34. -- Get stat
  35. local GetStat = Workspace:WaitForChild('DataPersistence'):WaitForChild('GetStat')
  36.  
  37. -- the names of the models that store the armor in a charcter, per slot
  38. local ArmorNamesInCharacterBySlotName = {Head = 'HeadArmor', Body = 'BodyArmor', Legs = 'LegsArmor'}
  39. -- names of slots to slot index
  40. local AllSlotNames = {'Head', 'Body', 'Legs'}
  41. local AllEquipNames = {'HeadEquip', 'BodyEquip', 'LegsEquip'}
  42.  
  43. -- Copy the armor data into a local rather than leaving it in the lighting
  44. local OriginalArmorData = game.Lighting:WaitForChild('ArmorData')
  45. local ArmorData = OriginalArmorData:Clone()
  46.  
  47. -- The armor data for players
  48. local EquipSlots = {}
  49.  
  50. local PlayerAllItems = {}
  51. local PlayerPurgatory = {} -- List of bad items that could not be properly loaded
  52. local PlayerInventory = {}
  53. local PlayerEquips = {}
  54. local PlayerInventorySave = {}
  55. local PlayerCns = {}
  56. local PlayerTwinsTable = {}
  57. local IsLoaded = {}
  58.  
  59. local RemItemLock = false
  60.  
  61. -- Has the armor data been loaded at least once?
  62. local ArmorDataLoaded = false
  63. local ArmorDataTriedLoad = false
  64. local LastAssetString = nil
  65. local LocalShopDataValue = script:WaitForChild('ShopData')
  66.  
  67. function UpdateArmorData_Item(id)
  68. local contents = game.InsertService:LoadAsset(id):GetChildren()
  69. if #contents == 1 and contents[1] then
  70. local armorModel = contents[1]
  71. -- On the first run, destroy the backup items we have if we are able to find
  72. -- the ones on the site.
  73. if ArmorData:FindFirstChild(armorModel.Name) then
  74. if ArmorDataTriedLoad then
  75. -- Only use the new armor if no one in the game currently has it (so
  76. -- that no references will be invalidated)
  77. local found = false
  78. for _, p in pairs(game.Players:GetChildren()) do
  79. if PlayerAllItems[p] then
  80. for _, item in pairs(PlayerAllItems[p]:GetChildren()) do
  81. if item.Name == armorModel.Name then
  82. found = true
  83. break
  84. end
  85. end
  86. if found then
  87. break
  88. end
  89. end
  90. end
  91. if not found then
  92. -- No one has the item right now, clone it in
  93. ArmorData[armorModel.Name]:Destroy()
  94. OriginalArmorData[armorModel.Name]:Destroy()
  95. end
  96. else
  97. -- Armor data has not done an initial load yet, use the new armor
  98. ArmorData[armorModel.Name]:Destroy()
  99. OriginalArmorData[armorModel.Name]:Destroy()
  100. end
  101. end
  102. if not ArmorData:FindFirstChild(armorModel.Name) then
  103. -- create the item
  104. armorModel:Clone().Parent = ArmorData
  105. armorModel:Clone().Parent = OriginalArmorData
  106. end
  107. end
  108. end
  109.  
  110. function UpdateArmorData()
  111. local assetString;
  112. if FF_LOCAL_ARMOR_DATA then
  113. assetString = LocalShopDataValue.Value
  114. else
  115. assetString = game.MarketplaceService:GetProductInfo(123893658).Description
  116. end
  117. if assetString == LastAssetString then
  118. return
  119. end
  120. LastAssetString = assetString
  121. --
  122. local itemList = assetString:gmatch('items:{(.*)}')()
  123. local count = assetString:gmatch('count:(%d+)')()
  124. count = tonumber(count) -- Note: No, this can't be wrapped into the last line
  125. if itemList and count then
  126. local items = {}
  127. for id in itemList:gmatch('%d+') do
  128. table.insert(items, tonumber(id))
  129. end
  130. --
  131. if #items == count then
  132. for _, id in pairs(items) do
  133. UpdateArmorData_Item(id)
  134. end
  135. ArmorDataLoaded = true
  136. end
  137. end
  138. --
  139. ArmorDataTriedLoad = true
  140. end
  141.  
  142. QueueUpdateArmorData.OnInvoke = function()
  143. Spawn(UpdateArmorData)
  144. end
  145.  
  146.  
  147. -- Spawn the armor data updater thread
  148. UpdateArmorData()
  149. Spawn(function()
  150. while true do
  151. wait(30)
  152. UpdateArmorData()
  153. end
  154. end)
  155. if FF_LOCAL_ARMOR_DATA then
  156. LocalShopDataValue.Changed:connect(UpdateArmorData)
  157. end
  158.  
  159. -- Function to make an armor
  160. local function MakeItem(name)
  161. local def = ArmorData[name]
  162. local item = Create'Model'{
  163. Name = name;
  164. Create'ObjectValue'{
  165. Name = 'Def';
  166. Value = def;
  167. };
  168. Create'StringValue'{
  169. Name = 'Index';
  170. Value = '';
  171. };
  172. }
  173. local toIgnore = {Armor = true, Name = true, Desc = true, Slot = true, Thumbnail = true}
  174. for _, ch in pairs(def:GetChildren()) do
  175. if not toIgnore[ch.Name] then
  176. ch:Clone().Parent = item
  177. end
  178. end
  179. return item
  180. end
  181.  
  182. local function FitsInSlot(itemObject, slotName)
  183. return itemObject.Def.Value.Slot.Value == slotName
  184. end
  185.  
  186. local function IsEquipped(itemObject)
  187. return ArmorNamesInCharacterBySlotName[itemObject.Index.Value] ~= nil
  188. end
  189.  
  190.  
  191. -- functions to serialize in/out the inventory state to the persistent data
  192. local LETTERS = {
  193. 'a','b','c','d','e',
  194. 'f','g','h','i','j',
  195. 'k','l','m','n','o',
  196. 'p','q','r','s','t',
  197. 'u','v','w','x','y',
  198. 'z'
  199. }
  200. local function NumToLetters(key)
  201. if key < 26 then
  202. return LETTERS[key%26+1]
  203. else
  204. return LETTERS[math.floor(key/26)]..LETTERS[key%26+1]
  205. end
  206. end
  207. function SaveInventory(player)
  208. if not IsLoaded[player] then return end -- don't save unloaded inventories
  209. local inventory = PlayerInventory[player]
  210. --
  211. local nextKey = 0
  212. local keys = {}
  213. local translated = {}
  214. local function translate(key)
  215. if not translated[key] then
  216. translated[key] = NumToLetters(nextKey)
  217. keys[translated[key]] = key
  218. nextKey = nextKey + 1
  219. end
  220. return translated[key]
  221. end
  222. local str = 'return{'
  223. for i, slotName in pairs(AllSlotNames) do
  224. str = str..translate(slotName)..'={'
  225. -- save out the normal items
  226. for _, itemObject in pairs(PlayerAllItems[player]:GetChildren()) do
  227. if itemObject.Def.Value.Slot.Value == slotName then
  228. str = str..'{'..translate('Ident')..'="'..translate(itemObject.Def.Value.Name)..'",'
  229. -- Save out props
  230. for _, ch in pairs(itemObject:GetChildren()) do
  231. if ch.Name ~= 'Def' and (ch:IsA('StringValue') or ch:IsA('NumberValue') or ch:IsA('IntValue')) then
  232. str = str..translate(ch.Name)..'='
  233. if ch:IsA('StringValue') then
  234. str = str..'[['..ch.Value..']],'
  235. else
  236. str = str..tostring(ch.Value)..','
  237. end
  238. end
  239. end
  240. str = str..'},'
  241. end
  242. end
  243. -- save out the purgatory'd items
  244. if i == 1 then
  245. for _, purgatoryItem in pairs(PlayerPurgatory[player]) do
  246. str = str..'{'..translate('Ident')..'="'..translate(purgatoryItem.Ident)..'",'
  247. -- Save out the props
  248. for key, value in pairs(purgatoryItem) do
  249. if key ~= 'Ident' then
  250. if type(value) == 'string' then
  251. str = str..translate(key)..'=[['..value..']],'
  252. else
  253. str = str..translate(key)..'='..tostring(value)..','
  254. end
  255. end
  256. end
  257. --
  258. str = str..'},'
  259. end
  260. end
  261. --
  262. str = str..'},'
  263. end
  264. --
  265. str = str..'},{'
  266. for k, v in pairs(keys) do
  267. str = str..k..'="'..v..'",'
  268. end
  269. str = str..'}'
  270. --
  271. PlayerInventorySave[player].Set(str)
  272. end
  273. function LoadInventory(player)
  274. local allItems = PlayerAllItems[player]
  275.  
  276. -- clear out current entries in the inventory (There should be none)
  277. allItems:ClearAllChildren()
  278.  
  279. -- empty the inventory
  280. local inv = {}
  281. PlayerInventory[player] = inv
  282.  
  283. -- indicies that we need to fix
  284. local itemsToFixIndexFor = {}
  285.  
  286. -- now load the items
  287. local dat = PlayerInventorySave[player].Get()
  288. if not player.Parent then
  289. -- Player left, bail out
  290. return
  291. end
  292. if dat ~= '' then
  293. local f, err = loadstring(dat)
  294. if err then
  295. _G.ErrorOut("FATAL: Invalid Inventory State for "..player.Name)
  296. return
  297. end
  298. local data, lookup = f()
  299. local reverseLookup = {}
  300. for k, v in pairs(lookup) do reverseLookup[v] = k end
  301. --
  302. local purgatorySet = {}
  303. for slotName, listing in pairs(data) do
  304. for _, itemData in pairs(listing) do
  305. local ident = reverseLookup.Ident
  306. if ident and itemData[ident] then
  307. if ArmorData:FindFirstChild(lookup[itemData[ident]]) then
  308. -- we have a valid item, load it in
  309. local itemDef = ArmorData[lookup[itemData[ident]]]
  310. local newObject = Create'Model'{
  311. Name = itemDef.Name;
  312. Create'ObjectValue'{
  313. Name = 'Def';
  314. Value = itemDef;
  315. };
  316. Create'StringValue'{
  317. Name = 'Index';
  318. Value = '';
  319. };
  320. }
  321. local toIgnore = {Armor = true, Name = true, Desc = true, Slot = true,
  322. Thumbnail = true}
  323. for _, prop in pairs(itemDef:GetChildren()) do
  324. if not toIgnore[prop.Name] then
  325. local newProp = prop:Clone()
  326. newProp.Parent = newObject
  327. if reverseLookup[newProp.Name] and itemData[reverseLookup[newProp.Name]] then
  328. newProp.Value = itemData[reverseLookup[newProp.Name]]
  329. end
  330. end
  331. end
  332.  
  333. -- get Index
  334. if reverseLookup['Index'] then
  335. local index = itemData[reverseLookup['Index']]
  336. if index == '' or type(index) == 'number' then
  337. itemsToFixIndexFor[newObject] = index
  338. else
  339. newObject.Index.Value = index
  340. if ArmorNamesInCharacterBySlotName[index] then
  341. if PlayerEquips[player][index].Value then
  342. itemsToFixIndexFor[newObject] = true
  343. else
  344. PlayerEquips[player][index].Value = newObject
  345. end
  346. else
  347. local page, x, y = index:gmatch('(%d+):(%d+):(%d+)')()
  348. page, x, y = tonumber(page), tonumber(x), tonumber(y)
  349. if not inv[page] then inv[page] = {} end
  350. if not inv[page][x] then inv[page][x] = {} end
  351. if inv[page][x][y] then
  352. itemsToFixIndexFor[newObject] = true
  353. else
  354. inv[page][x][y] = newObject
  355. end
  356. end
  357. -- add it to the items list if it doesn't need to be fixed
  358. if not itemsToFixIndexFor[newObject] then
  359. newObject.Parent = allItems
  360. end
  361. end
  362. end
  363. else
  364. -- no def, put the item in purgatory.
  365. if not purgatorySet[itemData] then
  366. local purgatoryItem = {}
  367. purgatoryItem.Ident = lookup[itemData[ident]]
  368. for symbol, value in pairs(itemData) do
  369. if lookup[symbol] ~= 'Ident' then
  370. -- load all the props translated
  371. purgatoryItem[lookup[symbol]] = value
  372. end
  373. end
  374. purgatorySet[itemData] = true
  375. table.insert(PlayerPurgatory[player], purgatoryItem)
  376. end
  377. end
  378. else
  379. _G.ErrorOut("FATAL: Malformed data when loading inventory")
  380. end
  381. end
  382. end
  383. end
  384.  
  385. -- fix up indicies from the old flat indexing to the new paged inventory layout
  386. for itemObject, index in pairs(itemsToFixIndexFor) do
  387. itemObject.Index.Value = ''
  388. if index == 1 then
  389. -- We should try to equip this one, it was equipped before
  390. if not TryToEquip(player, itemObject) then
  391. FindSlotFor(player, itemObject)
  392. end
  393. else
  394. FindSlotFor(player, itemObject)
  395. end
  396. -- add it to the items list
  397. itemObject.Parent = allItems
  398. end
  399.  
  400. IsLoaded[player] = true
  401. end
  402.  
  403.  
  404. function FindSlotFor(player, itemObject)
  405. if itemObject.Index.Value ~= '' then return true end
  406. local inv = PlayerInventory[player]
  407. for page = 1, TMP_PAGE_COUNT do
  408. for y = 1, PAGE_HEIGHT do
  409. for x = 1, PAGE_WIDTH do
  410. if not inv[page] or not inv[page][x] or not inv[page][x][y] then
  411. if not inv[page] then inv[page] = {} end
  412. if not inv[page][x] then inv[page][x] = {} end
  413. inv[page][x][y] = itemObject
  414. itemObject.Index.Value = page..':'..x..':'..y
  415. return true
  416. end
  417. end
  418. end
  419. end
  420. return false
  421. end
  422.  
  423.  
  424. -- Returns: Whether the equip was successfull
  425. function TryToEquip(player, itemObject)
  426. if IsEquipped(itemObject) then
  427. -- we are already equipped
  428. return true
  429. end
  430. local inv = PlayerInventory[player]
  431. for _, slotName in pairs(AllSlotNames) do
  432. if FitsInSlot(itemObject, slotName) then
  433. local slot = PlayerEquips[player][slotName]
  434. if slot and not slot.Value then
  435. local page, x, y = itemObject.Index.Value:gmatch('(%d+):(%d+):(%d+)')()
  436. if page then
  437. inv[page][x][y] = nil
  438. elseif itemObject.Index.Value == '' then
  439. -- nothing to do
  440. else
  441. _G.ErrorOut("Bad item index found: "..itemObject.Index.Value)
  442. return false
  443. end
  444. slot.Value = itemObject
  445. itemObject.Index.Value = slotName
  446. return true
  447. end
  448. end
  449. end
  450. return false
  451. end
  452.  
  453.  
  454. function FindOriginalItemFor(player, twin)
  455. for itemObject, twinObject in pairs(PlayerTwinsTable[player]) do
  456. if twinObject == twin then
  457. return itemObject
  458. end
  459. end
  460. return nil
  461. end
  462.  
  463.  
  464. -- Function to reorder the inventory
  465. function MoveInventoryItemToSlot(player, twinItemObject, page, x, y)
  466. -- Error checking
  467. if not page or not x or not y then print("Missing arg") return end
  468. if page > TMP_PAGE_COUNT or page < 1 then print("Bad page") return end
  469. if x < 1 or y < 1 or x > PAGE_WIDTH or y > PAGE_HEIGHT then print("Bad coord") return end
  470. --
  471. local inv = PlayerInventory[player]
  472. local itemObject = FindOriginalItemFor(player, twinItemObject)
  473. --
  474. if not itemObject then print("Invalid item") return end
  475. if itemObject.Index.Value == '' then print("Empty index for item to swap") return end
  476. --
  477. local mypage, myx, myy = itemObject.Index.Value:gmatch('(%d+):(%d+):(%d+)')()
  478. mypage, myx, myy = tonumber(mypage), tonumber(myx), tonumber(myy)
  479. --
  480. -- if we were equipped, clear the equip
  481. if IsEquipped(itemObject) then
  482. PlayerEquips[player][itemObject.Index.Value].Value = nil
  483. elseif not mypage or not myx or not myy then
  484. print("Item at non-numeric index")
  485. return
  486. else
  487. inv[mypage][myx][myy] = nil
  488. end
  489. --
  490. local swapItemObject = ((inv[page] or {})[x] or {})[y]
  491. if swapItemObject then
  492. -- Do a swap
  493. if IsEquipped(itemObject) then
  494. -- Can't swap if one of the items would be left in a slot that it's not allowed in
  495. if not FitsInSlot(swapItemObject, itemObject.Index.Value) then
  496. print("Swap bad, equip item ", swapItemObject, "to slot", itemObject.Index.Value)
  497. return
  498. end
  499. swapItemObject.Index.Value = itemObject.Index.Value
  500. PlayerEquips[player][swapItemObject.Index.Value].Value = swapItemObject
  501. else
  502. swapItemObject.Index.Value = itemObject.Index.Value
  503. inv[mypage][myx][myy] = swapItemObject
  504. end
  505. end
  506.  
  507. -- Update this item index
  508. itemObject.Index.Value = page..':'..x..':'..y
  509.  
  510. -- Actually add to inv table
  511. if not inv[page] then inv[page] = {} end
  512. if not inv[page][x] then inv[page][x] = {} end
  513. inv[page][x][y] = itemObject
  514.  
  515. -- And save the inv with the update
  516. SaveInventory(player)
  517. end
  518.  
  519. -- Function to reorder the inv
  520. function MoveInventoryItemToEquip(player, twinItemObject, slotName)
  521. -- Error checking
  522. if not slotName then print("Missing slot name") return end
  523. if not ArmorNamesInCharacterBySlotName[slotName] then print("Bad slot name") return end
  524. --
  525. local inv = PlayerInventory[player]
  526. local itemObject = FindOriginalItemFor(player, twinItemObject)
  527. --
  528. if not itemObject then print("Invalid item") return end
  529. if itemObject.Index.Value == '' then print("Empty index for item to swap") return end
  530. --
  531. local mypage, myx, myy = itemObject.Index.Value:gmatch('(%d+):(%d+):(%d+)')()
  532. mypage, myx, myy = tonumber(mypage), tonumber(myx), tonumber(myy)
  533. --
  534. -- if we were equipped, clear the equip
  535. if IsEquipped(itemObject) then
  536. PlayerEquips[player][itemObject.Index.Value].Value = nil
  537. elseif not mypage or not myx or not myy then
  538. print("Item at non-numeric index")
  539. return
  540. else
  541. inv[mypage][myx][myy] = nil
  542. end
  543. --
  544. local swapItemObject = PlayerEquips[player][slotName].Value
  545. if swapItemObject then
  546. -- Do a swap
  547. if IsEquipped(itemObject) then
  548. -- Can't swap if one of the items would be left in a slot that it's not allowed in
  549. if not FitsInSlot(swapItemObject, itemObject.Index.Value) then
  550. print("Swap bad, equip item ", swapItemObject, "to slot", itemObject.Index.Value)
  551. return
  552. end
  553. swapItemObject.Index.Value = itemObject.Index.Value
  554. PlayerEquips[player][swapItemObject.Index.Value].Value = swapItemObject
  555. else
  556. swapItemObject.Index.Value = itemObject.Index.Value
  557. inv[mypage][myx][myy] = swapItemObject
  558. end
  559. end
  560. itemObject.Index.Value = slotName
  561. PlayerEquips[player][slotName].Value = itemObject
  562. -- And save the inv with the update
  563. SaveInventory(player)
  564. end
  565.  
  566.  
  567. -- Give a player an item
  568. function _G.AwardItem(player, itemName)
  569. -- Make sure we get the most recent armor data
  570. UpdateArmorData()
  571.  
  572. if ArmorData:FindFirstChild(itemName) then
  573. local item = MakeItem(itemName)
  574. item.Parent = PlayerAllItems[player]
  575. return true
  576. else
  577. return false
  578. end
  579. end
  580.  
  581.  
  582. -- Get the cost of an item
  583. GetItemCost.OnInvoke = function(itemName)
  584. local item = ArmorData:FindFirstChild(itemName)
  585. if item then
  586. local cost = item:FindFirstChild('Cost')
  587. if cost then
  588. return cost.Value
  589. else
  590. return 0
  591. end
  592. else
  593. return nil
  594. end
  595. end
  596.  
  597.  
  598. -- check if an inv is full
  599. IsInventoryFull.OnInvoke = function(player)
  600. local inv = PlayerInventory[player]
  601. for page = 1, TMP_PAGE_COUNT do
  602. if inv[page] then
  603. for x = 1, PAGE_WIDTH do
  604. if inv[page][x] then
  605. for y = 1, PAGE_HEIGHT do
  606. if not inv[page][x][y] then
  607. return false
  608. end
  609. end
  610. else
  611. return false
  612. end
  613. end
  614. else
  615. return false
  616. end
  617. end
  618. return true
  619. end
  620.  
  621.  
  622. function MakeArmorstatsMirror(player)
  623. local armorstats = Instance.new('Model')
  624. armorstats.Name = 'armorstats'
  625.  
  626. local HeadEquip = Instance.new('ObjectValue', armorstats)
  627. HeadEquip.Name = 'HeadEquip'
  628.  
  629. local BodyEquip = Instance.new('ObjectValue', armorstats)
  630. BodyEquip.Name = 'BodyEquip'
  631.  
  632. local LegsEquip = Instance.new('ObjectValue', armorstats)
  633. LegsEquip.Name = 'LegsEquip'
  634.  
  635. local AllItems = Instance.new('Model', armorstats)
  636. AllItems.Name = 'AllItems'
  637.  
  638. armorstats.Parent = player
  639. return armorstats
  640. end
  641.  
  642.  
  643. -- Handle inventory for entering and leaving players
  644. function onPlayerEntered(player)
  645. -- Make an inventory table for them
  646. local inv = {}
  647. PlayerInventory[player] = inv
  648.  
  649. -- get the save
  650. PlayerInventorySave[player] = GetStat:Invoke(player, 'Inventory')()
  651. if not player.Parent then
  652. -- Bail out, player left right away
  653. return
  654. end
  655.  
  656. -- Make the armor stats mirror
  657. local armorstats = MakeArmorstatsMirror(player)
  658.  
  659. -- Make an allitems for them
  660. local allItems = Create'Model'{
  661. Name = 'AllItems';
  662. }
  663. local allItemsMirror = player.armorstats.AllItems
  664. PlayerAllItems[player] = allItems
  665.  
  666. -- create purgatory
  667. PlayerPurgatory[player] = {}
  668.  
  669. -- Set up tracking for that allitems twinning
  670. local objectToTwin = {}
  671.  
  672. -- make the equipped slots
  673. local equips = {}
  674. local modifiers = {}
  675. for i, equipName in pairs(AllEquipNames) do
  676. local slotName = AllSlotNames[i]
  677. equips[slotName] = Create'ObjectValue'{
  678. Name = equipName;
  679. }
  680. modifiers[slotName] = {}
  681. equips[slotName].Changed:connect(function()
  682. -- Remove old modifiers
  683. for _, modifier in pairs(modifiers[slotName]) do
  684. RemoveModifier:Invoke(player, modifier)
  685. end
  686. modifiers[slotName] = {}
  687. -- Apply new modifiers
  688. local itemObject = equips[slotName].Value
  689. if itemObject then
  690. local def = itemObject:FindFirstChild('Def')
  691. if def and def.Value then
  692. local modifierList = def.Value:FindFirstChild('Modifiers')
  693. print(modifierList)
  694. if modifierList then
  695. for _, modifier in pairs(modifierList:GetChildren()) do
  696. table.insert(modifiers[slotName], AddModifier:Invoke(player, modifier.Name, modifier.Value))
  697. end
  698. end
  699. end
  700. end
  701. end)
  702. -- mirror it
  703. local mirror = armorstats[equipName]
  704. mirror.Changed:connect(function(pr)
  705. -- Reparenter
  706. if pr == 'Parent' then
  707. mirror.Parent = armorstats
  708. end
  709. end)
  710. equips[slotName].Changed:connect(function()
  711. if equips[slotName].Value then
  712. while not objectToTwin[equips[slotName].Value] do wait() end
  713. end
  714. mirror.Value = objectToTwin[equips[slotName].Value]
  715. end)
  716. end
  717. PlayerEquips[player] = equips
  718. PlayerTwinsTable[player] = objectToTwin
  719. local twinObjectToRecreate = {}
  720. local itemAddCn = allItems.ChildAdded:connect(function(itemObject)
  721. -- set up twinning for the child
  722. local lastTwinCn;
  723. local function makeTwin()
  724. if lastTwinCn then
  725. lastTwinCn:disconnect()
  726. lastTwinCn = nil
  727. end
  728. local twin = itemObject:Clone()
  729. objectToTwin[itemObject] = twin
  730. twin.Parent = allItemsMirror
  731. itemObject.ChildAdded:connect(function(ch)
  732. -- twin the child
  733. local chTwin = ch:Clone()
  734. chTwin.Parent = twin
  735.  
  736. -- on changed update
  737. ch.Changed:connect(function()
  738. chTwin.Value = ch.Value
  739. end)
  740. end)
  741. lastTwinCn = itemObject.ChildRemoved:connect(function(ch)
  742. twin:Destroy()
  743. end)
  744. for _, ch in pairs(itemObject:GetChildren()) do
  745. local twinCh = twin[ch.Name]
  746. ch.Changed:connect(function()
  747. twinCh.Value = ch.Value
  748. end)
  749. end
  750. -- change the twin def to point to the lighting armordata
  751. twin.Def.Value = OriginalArmorData:FindFirstChild(itemObject.Def.Value.Name)
  752. -- save it
  753. twinObjectToRecreate[twin] = makeTwin
  754. return twin
  755. end
  756. makeTwin()
  757.  
  758. -- set the inv table
  759. if not FindSlotFor(player, itemObject) then
  760. TryToEquip(player, itemObject)
  761. end
  762.  
  763. -- save the change
  764. SaveInventory(player)
  765.  
  766. -- handle killing it when it's condition reaches 0
  767. if itemObject:FindFirstChild('MaxHealth') and itemObject.MaxHealth.Value > 0 then
  768. local conditionValue = itemObject:FindFirstChild('Condition')
  769. if conditionValue then
  770. if conditionValue.Value == 0 then
  771. Delay(0, function()
  772. itemObject.Parent = nil
  773. end)
  774. end
  775. conditionValue.Changed:connect(function()
  776. if conditionValue.Value <= 0.00001 then
  777. Delay(0, function()
  778. itemObject.Parent = nil
  779. end)
  780. else
  781. SaveInventory(player)
  782. end
  783. end)
  784. end
  785. end
  786. end)
  787. local itemRemCn = allItems.ChildRemoved:connect(function(itemObject)
  788. if objectToTwin[itemObject] then
  789. RemItemLock = true
  790. objectToTwin[itemObject]:Destroy()
  791. objectToTwin[itemObject] = nil
  792. RemItemLock = false
  793. end
  794.  
  795. -- item removed, remove it from the inv or equip slot
  796. if IsEquipped(itemObject) then
  797. PlayerEquips[player][itemObject.Index.Value].Value = nil
  798. else
  799. local page, x, y = itemObject.Index.Value:gmatch('(%d+):(%d+):(%d+)')()
  800. PlayerInventory[player][tonumber(page)][tonumber(x)][tonumber(y)] = nil
  801. end
  802.  
  803. -- save the change
  804. SaveInventory(player)
  805. end)
  806. -- recreate twins on removed
  807. player:WaitForChild('armorstats'):WaitForChild('AllItems').ChildRemoved:connect(function(ch)
  808. if not RemItemLock and twinObjectToRecreate[ch] then
  809. twinObjectToRecreate[ch]()
  810. end
  811. end)
  812. armorstats.Changed:connect(function(pr)
  813. if pr == 'Parent' then
  814. -- Reparenter
  815. armorstats.Parent = player
  816. end
  817. end)
  818. allItemsMirror.Changed:connect(function(pr)
  819. if pr == 'Parent' then
  820. -- Reparenter
  821. allItemsMirror.Parent = armorstats
  822. end
  823. end)
  824. PlayerCns[player] = {itemAddCn, itemRemCn}
  825.  
  826. -- Now, load in the inventory
  827. LoadInventory(player)
  828.  
  829. -- If we have the basics, remove them from the inv
  830. if allItems:FindFirstChild('BasicHead') then
  831. allItems.BasicHead.Parent = nil
  832. end
  833. if allItems:FindFirstChild('BasicLegs') then
  834. allItems.BasicLegs.Parent = nil
  835. end
  836. if allItems:FindFirstChild('BasicBody') then
  837. allItems.BasicBody.Parent = nil
  838. end
  839. end
  840. function onPlayerLeaving(player)
  841. if not player:IsA('Player') then return end
  842.  
  843. -- disconnect stuff
  844. if PlayerCns[player] then
  845. for _, cn in pairs(PlayerCns[player]) do
  846. cn:disconnect()
  847. end
  848. end
  849.  
  850. -- clean up their values. Note, this will succeed no matter what point
  851. -- initialization got to.
  852. PlayerInventory[player] = nil
  853. PlayerEquips[player] = nil
  854. PlayerAllItems[player] = nil
  855. PlayerCns[player] = nil
  856. PlayerTwinsTable[player] = nil
  857. PlayerPurgatory[player] = nil
  858. PlayerInventorySave[player] = nil
  859. end
  860. game.Players.PlayerAdded:connect(onPlayerEntered)
  861. for _, player in pairs(game.Players:GetChildren()) do
  862. onPlayerEntered(player)
  863. end
  864. game.Players.ChildRemoved:connect(onPlayerLeaving)
  865.  
  866.  
  867. -- Handle messages
  868. script.ChildAdded:connect(function(ch)
  869. if not ch:IsA('ObjectValue') then return end
  870.  
  871. -- wait on name
  872. while ch.Name == 'Value' do ch.Changed:wait() end
  873. while not ch.Value do ch.Changed:wait() end
  874. --
  875. local player = ch.Value
  876. if not player:IsA('Player') then return end
  877. --
  878. Delay(0.2, function()
  879. ch:Destroy()
  880. end)
  881. --
  882. if ch.Name == 'MoveItem' then
  883. local item = WaitForValueObjectValue(ch, 'Item', nil)
  884. if not ch.Parent then return end
  885. local targetIndex = WaitForValueObjectValue(ch, 'TargetIndex', '')
  886. if ArmorNamesInCharacterBySlotName[targetIndex] then
  887. MoveInventoryItemToEquip(player, item, targetIndex)
  888. else
  889. local page, x, y = targetIndex:gmatch('(%d+):(%d+):(%d+)')()
  890. --
  891. MoveInventoryItemToSlot(player, item, tonumber(page), tonumber(x), tonumber(y))
  892. end
  893. --
  894. elseif ch.Name == 'PluginAwardItem' then
  895. -- local itemName = WaitForValueObjectValue(ch, 'Ident', '')
  896. -- MakeItem(itemName).Parent = PlayerAllItems[player]
  897. elseif ch.Name == 'AblateArmor' then
  898. local itemModel = WaitForValueObjectValue(ch, 'Armor', nil)
  899. if not ch.Parent then return end
  900. local damage = WaitForValueObjectValue(ch, 'AblationDamage', 0)
  901. -- translate itemModel
  902. if player.Parent then
  903. local found = false
  904. for model, twin in pairs(PlayerTwinsTable[player]) do
  905. if twin == itemModel then
  906. itemModel = model
  907. found = true
  908. break
  909. end
  910. end
  911. if found then
  912. if itemModel:FindFirstChild('MaxHealth') and itemModel:FindFirstChild('Condition') then
  913. itemModel.Condition.Value = math.max(0, itemModel.Condition.Value - damage/itemModel.MaxHealth.Value)
  914. end
  915. end
  916. end
  917. end
  918. end)
  919.  
  920.  
  921. --==========================================================================================================--
  922. --== Armor drawing part of the code
  923. --==
  924.  
  925.  
  926. -- equip a character with a given armor look
  927. -- Returns: A connection that needs to be disconnected when the
  928. -- item is unequipped. (There isn't a better way to do that?)
  929. function DoEquipItem(player, item)
  930. if not player.Character then return end
  931. local Character = player.Character
  932. --
  933. local itemDef = WaitForValueObjectValue(item, 'Def', nil)
  934. if not item.Parent then return end -- check that the item still exists
  935. --
  936. local slotName = WaitForValueObjectValue(itemDef, 'Slot', '')
  937. if not item.Parent then return end -- check that the item still exists
  938. local modelName = ArmorNamesInCharacterBySlotName[slotName]
  939. --
  940. local partDefs = itemDef:WaitForChild('Armor')
  941. if not item.Parent then return end -- check that the item still exists
  942.  
  943. -- get rid of the old armor if it exists
  944. if Character:FindFirstChild(modelName) then -- remove armor
  945. Character[modelName]:Destroy()
  946. end
  947.  
  948. -- make a new armor
  949. local armorModel = Create'Model'{
  950. Name = modelName;
  951. Parent = Character;
  952. }
  953.  
  954. -- copy over components from the armor def
  955. local allArmorFadeParts = {}
  956. for _, chPart in pairs(Character:GetChildren()) do
  957. if chPart:IsA('BasePart') then
  958. local basePart = partDefs:FindFirstChild(chPart.Name)
  959. if basePart then
  960. for _, w in pairs(basePart:GetChildren()) do
  961. if w:IsA('JointInstance') then
  962. -- make the armor part
  963. local attachedPart = w.Part1:Clone()
  964. attachedPart.Parent = armorModel
  965. local newW = w:Clone()
  966. newW.Parent = attachedPart
  967. newW.Part0 = chPart
  968. newW.Part1 = attachedPart
  969. -- is it a fade part?
  970. if attachedPart:FindFirstChild('Fade') and attachedPart.Fade.Value then
  971. table.insert(allArmorFadeParts, attachedPart)
  972. end
  973. end
  974. end
  975. end
  976. end
  977. end
  978.  
  979. -- add coloration
  980. if partDefs:FindFirstChild('BaseColor') then
  981. partDefs.BaseColor:Clone().Parent = Character
  982. end
  983.  
  984. -- handle condition
  985. local conditionValue = item:FindFirstChild('Condition')
  986. if conditionValue then
  987. local function UpdateCondition()
  988. local condition = conditionValue.Value
  989. if condition < 0.8 then
  990. condition = condition / 0.8
  991. local trans = 0.5*(1-condition)
  992. --
  993. for _, part in pairs(allArmorFadeParts) do
  994. part.Transparency = trans
  995. end
  996. end
  997. end
  998. local cn = conditionValue.Changed:connect(UpdateCondition)
  999. UpdateCondition()
  1000. end
  1001.  
  1002. --
  1003. return cn
  1004. end
  1005.  
  1006.  
  1007. -- unequip a character of all armors in a given slot
  1008. function DoUnequipItem(player, slotName)
  1009. if player.Character then
  1010. local modelName = ArmorNamesInCharacterBySlotName[slotName]
  1011. local armorModel = player.Character:FindFirstChild(modelName)
  1012. if armorModel then armorModel:Destroy() end
  1013. end
  1014. end
  1015.  
  1016.  
  1017. -- connect up a player to do equipping of armor
  1018. function HandlePlayer(player)
  1019. local Armorstats = player:WaitForChild('armorstats')
  1020. if not player.Parent then return end
  1021. --
  1022. local HeadEquip = Armorstats:WaitForChild('HeadEquip')
  1023. if not player.Parent then return end
  1024. local BodyEquip = Armorstats:WaitForChild('BodyEquip')
  1025. if not player.Parent then return end
  1026. local LegsEquip = Armorstats:WaitForChild('LegsEquip')
  1027. if not player.Parent then return end
  1028. local AllItems = Armorstats:WaitForChild('AllItems')
  1029. if not player.Parent then return end
  1030. --
  1031. local SlotNameToEquipValue = {Head = HeadEquip, Body = BodyEquip, Legs = LegsEquip}
  1032.  
  1033. -- for each armor slot
  1034. for slotName, equipValue in pairs(SlotNameToEquipValue) do
  1035. local lastEquipCn;
  1036. local lastEquippedItem;
  1037.  
  1038. -- when a new item is equipped... update
  1039. equipValue.Changed:connect(function()
  1040. if equipValue.Value and equipValue.Value ~= lastEquippedItem then
  1041. if lastEquipCn then lastEquipCn:disconnect() end
  1042. lastEquippedItem = equipValue.Value
  1043. lastEquipCn = DoEquipItem(player, equipValue.Value)
  1044. else
  1045. lastEquippedItem = nil
  1046. DoUnequipItem(player, slotName)
  1047. end
  1048. end)
  1049.  
  1050. -- update when we first load
  1051. if equipValue.Value and equipValue.Value ~= lastEquippedItem then
  1052. if lastEquipCn then lastEquipCn:disconnect() end
  1053. lastEquippedItem = equipValue.Value
  1054. lastEquipCn = DoEquipItem(player, equipValue.Value)
  1055. end
  1056.  
  1057. -- update when a character respawns
  1058. player.CharacterAdded:connect(function(character)
  1059. if equipValue.Value then
  1060. if lastEquipCn then lastEquipCn:disconnect() end
  1061. lastEquipCn = DoEquipItem(player, equipValue.Value)
  1062. end
  1063. local hum = character:WaitForChild('Humanoid')
  1064. hum.Died:wait()
  1065. -- Make armor cancollide on death
  1066. for _, armorModelName in pairs(ArmorNamesInCharacterBySlotName) do
  1067. if character:FindFirstChild(armorModelName) then
  1068. for _, part in pairs(character[armorModelName]:GetChildren()) do
  1069. if part:IsA('BasePart') then
  1070. part.CanCollide = true
  1071. end
  1072. end
  1073. end
  1074. end
  1075. end)
  1076. end
  1077. end
  1078.  
  1079.  
  1080. -- main connection
  1081. game.Players.ChildAdded:connect(HandlePlayer)
  1082. for _, p in pairs(game.Players:GetChildren()) do
  1083. HandlePlayer(p)
  1084. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement