Advertisement
yal_f

ally system

Aug 9th, 2024
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.56 KB | None | 0 0
  1. --!optimize 2
  2. --!native
  3.  
  4. local RepStorage = game:FindService("ReplicatedStorage")
  5. local ServerStorage = game:FindService("ServerStorage")
  6. local RunService = game:GetService("RunService")
  7.  
  8. local remotes = RepStorage.Remotes
  9.  
  10. local clientModules = RepStorage.Modules
  11. local allyData = require(clientModules.AllyData)
  12. local pathModule = require(clientModules.PathModule)
  13.  
  14. local serverModules = ServerStorage.Modules
  15. local enemyHandler = require(serverModules.EnemyHandler)
  16. local targetingFuncs = require(serverModules.TargetingFunctions)
  17.  
  18. local DamageEnemy = enemyHandler.DamageEnemy
  19. local RemoveEnemy = enemyHandler.RemoveEnemy
  20. local FindNodeAfterPoint = pathModule.FindNodeAfterPoint
  21. local FindNodeBeforePoint = pathModule.FindNodeBeforePoint
  22. local paths = pathModule.paths
  23. local enemies = enemyHandler.enemies
  24.  
  25. local IDcount = 0
  26. local allies = {}
  27.  
  28. --
  29.  
  30. local IDX_POS = 1
  31. local IDX_DIST = 2
  32.  
  33. --
  34.  
  35. local function RemoveAlly(ally)
  36.     ally.dead = true
  37.    
  38.     local ID = ally.ID
  39.    
  40.     allies[ID] = nil
  41.     remotes.RemoveAlly:FireAllClients(ID)
  42.    
  43.     local DeathFunc = ally.funcs.OnDeath
  44.     if DeathFunc then
  45.         task.spawn(DeathFunc, ally)
  46.     end
  47. end
  48.  
  49. local function DamageAlly(ally, damageAmount: number, bypassShield: boolean?) --returns true damage amount
  50.     local health = ally.health
  51.     local shield = ally.shield
  52.  
  53.     if shield and shield ~= 0 and not bypassShield then
  54.         local allyID = ally.ID
  55.         local buf = buffer.create(8)
  56.         buffer.writeu32(buf, 0, allyID)
  57.        
  58.         if damageAmount >= shield then
  59.             ally.shield = 0
  60.             local ShieldBreakFunc = ally.funcs.OnShieldBreak
  61.             if ShieldBreakFunc then task.spawn(buf) end
  62.             remotes.UpdateAllyShield:FireAllClients(buf)
  63.            
  64.             return shield
  65.         end
  66.        
  67.         local newShield = shield - damageAmount
  68.         ally.shield = newShield
  69.        
  70.         buffer.writef32(buf, 4, newShield)
  71.         remotes.UpdateAllyShield:FireAllClients(buf)
  72.     else
  73.         if damageAmount >= health then
  74.             RemoveAlly(ally)
  75.             return health
  76.         end
  77.        
  78.         local newHealth = health - damageAmount
  79.         ally.health = newHealth
  80.        
  81.         local allyID = ally.ID
  82.         local buf = buffer.create(8)
  83.         buffer.writeu32(buf, 0, allyID)
  84.         buffer.writef32(buf, 4, newHealth)
  85.         remotes.UpdateAllyHealth:FireAllClients(buf)
  86.     end
  87.    
  88.     return damageAmount
  89. end
  90.  
  91. local function UnitRam(ally, enemy)
  92.     local allyShield = ally.shield
  93.     local allyHealth = ally.health
  94.     DamageEnemy(enemy, if allyShield then allyHealth + allyShield else allyHealth, ally.player_name, nil, true)
  95.    
  96.     local enemyShield = enemy.shield
  97.     local enemyHealth = enemy.health
  98.     DamageAlly(ally, if enemyShield then enemyHealth + enemyShield else enemyHealth)
  99.     return ally.dead
  100. end
  101.  
  102. local function AddAlly(spawnData)
  103.     IDcount += 1
  104.    
  105.     local allyType = spawnData.kind
  106.     local playerName = spawnData.player
  107.     local distance = spawnData.distance
  108.     local pathIndex = spawnData.path or math.random(#paths)
  109.    
  110.     local allyInfo = allyData[allyType]
  111.     local path = paths[pathIndex]
  112.     local pathLength = #path
  113.     local funcs = allyInfo.Functions and require(allyInfo.Functions)
  114.    
  115.     local offset = Vector3.new(
  116.         if allyInfo.NoPathOffset then 0 else Random.new(IDcount):NextNumber(-0.5, 0.5),
  117.         allyInfo.Model:GetExtentsSize().Y / 2,
  118.         0
  119.     )
  120.    
  121.     --
  122.  
  123.     remotes.AddAlly:FireAllClients(IDcount, workspace:GetServerTimeNow(), allyType, distance, pathIndex)
  124.  
  125.     local nodeIndex, trackPos, trackCFrame
  126.     if distance then
  127.         nodeIndex = FindNodeBeforePoint(path, pathLength, distance)
  128.  
  129.         local nodeA = path[nodeIndex]
  130.         local nodeB = path[nodeIndex+1]
  131.        
  132.         local dir = (nodeB[IDX_POS] - nodeA[IDX_POS]).Unit
  133.         trackPos = nodeA[IDX_POS] + dir * (distance - nodeA[IDX_DIST])
  134.         trackCFrame = CFrame.lookAlong(trackPos, -dir)
  135.     else
  136.         nodeIndex = pathLength
  137.         trackPos = path[pathLength][IDX_POS]
  138.         trackCFrame = CFrame.lookAt(trackPos, path[pathLength-1][IDX_POS])
  139.     end
  140.    
  141.     if funcs and funcs.Main then
  142.         task.defer(funcs.Main, IDcount)
  143.     end
  144.  
  145.     local enemy = {
  146.         ID = IDcount,
  147.         ally_type = allyType,
  148.         path = pathIndex,
  149.         player_name = playerName,
  150.  
  151.         track_pos = trackPos,
  152.         true_pos = trackCFrame * offset,
  153.         offset_normal = offset,
  154.         distance = distance or path[pathLength][IDX_DIST],
  155.         dead = false,
  156.        
  157.         display_speed = nil,
  158.         speed = allyInfo.Speed,
  159.         health = allyInfo.MaxHealth,
  160.         max_health = allyInfo.MaxHealth,
  161.         shield = allyInfo.Shield,
  162.         ghost = allyInfo.Ghost,
  163.         float = allyInfo.Float,
  164.  
  165.         node_index = nodeIndex,
  166.         funcs = funcs or {}
  167.     }
  168.    
  169.     allies[IDcount] = enemy
  170.     return enemy
  171. end
  172.  
  173. local function StepAlly(ally, amount: number)
  174.     local backwards = amount < 0
  175.  
  176.     local path = paths[ally.path]
  177.     local newDist = math.min(ally.distance - amount, path[#path][IDX_DIST])
  178.  
  179.     if newDist > 0 then
  180.         local nodeIndex = (if backwards then FindNodeAfterPoint else FindNodeBeforePoint)(path, ally.node_index, newDist)
  181.  
  182.         local nodeA = path[nodeIndex]
  183.         local nodeB = path[nodeIndex+1]
  184.        
  185.         local dir = (nodeB[IDX_POS] - nodeA[IDX_POS]).Unit
  186.         local allyTrackPos = (nodeA[IDX_POS] + dir * (newDist - nodeA[IDX_DIST]))
  187.  
  188.         --
  189.        
  190.         if not ally.ghost then
  191.             local allyFloat = ally.float
  192.             local allyPos = if allyFloat then allyTrackPos + (Vector3.yAxis * allyFloat) else allyTrackPos
  193.             local rangeSquared = allyData[ally.ally_type].Hit_Range^2
  194.            
  195.             for _, enemy in enemies do
  196.                 local dif = (enemy.track_pos - allyPos)
  197.                 local enemyFloat = enemy.float
  198.                
  199.                 if (dif.X^2 + (if enemyFloat then dif.Y + enemyFloat else dif.Y)^2 + dif.Z^2) <= rangeSquared and UnitRam(ally, enemy) then
  200.                     return
  201.                 end
  202.             end
  203.         end
  204.        
  205.         ally.distance = newDist
  206.         ally.node_index = nodeIndex
  207.         ally.track_pos = allyTrackPos
  208.         ally.true_pos = CFrame.lookAlong(allyTrackPos, dir) * ally.offset_normal
  209.     else
  210.         RemoveAlly(ally)
  211.     end
  212. end
  213.  
  214. --
  215.  
  216. RunService.PreSimulation:Connect(function(dt)
  217.     for _, ally in allies do
  218.         StepAlly(ally, (ally.display_speed or ally.speed) * dt)
  219.     end
  220. end)
  221.  
  222. --
  223.  
  224. local function GetAllyCount()
  225.     local count = 0
  226.  
  227.     for _ in allies do
  228.         count += 1
  229.     end
  230.     return count
  231. end
  232.  
  233. local function GetRandomAlly(flyingDet: boolean?)
  234.     local indicies = {}
  235.     local count = 0
  236.  
  237.     for ID, ally in allies do
  238.         if not flyingDet and ally.float then continue end
  239.        
  240.         count += 1
  241.         indicies[count] = ID
  242.     end
  243.     return #indicies ~= 0 and indicies[math.random(#indicies)]
  244. end
  245.  
  246. local function GetAlliesInRange(pos: Vector3, range: number, flyingDet: boolean?)
  247.     local rangeSquared = range^2
  248.    
  249.     local validIndicies = {}
  250.     local count = 0
  251.  
  252.     for ID, ally in allies do
  253.         if not flyingDet and ally.float then continue end
  254.        
  255.         local dif = (allies.track_pos - pos)
  256.         local float = ally.Float
  257.        
  258.         if (dif.X^2 + (if float then dif.Y + float else dif.Y)^2 + dif.Z^2) <= rangeSquared then
  259.             count += 1
  260.             validIndicies[count] = ID
  261.         end
  262.     end
  263.     return #validIndicies ~= 0 and validIndicies
  264. end
  265.  
  266. local function GetAlliesInRange2D(pos: Vector3, range: number, flyingDet: boolean?)
  267.     local rangeSquared = range^2
  268.    
  269.     local validIndicies = {}
  270.     local count = 0
  271.  
  272.     for ID, ally in allies do
  273.         if not flyingDet and ally.float then continue end
  274.        
  275.         local dif = (allies.track_pos - pos)
  276.        
  277.         if (dif.X^2 + dif.Z^2) <= rangeSquared then
  278.             count += 1
  279.             validIndicies[count] = ID
  280.         end
  281.     end
  282.     return #validIndicies ~= 0 and validIndicies
  283. end
  284. local function GetAllAllies(flyingDet: boolean?)
  285.     local indicies = {}
  286.     local count = 0
  287.  
  288.     for ID, ally in allies do
  289.         if not flyingDet and ally.float then continue end
  290.        
  291.         count += 1
  292.         indicies[count] = ID
  293.     end
  294.     return indicies
  295. end
  296.  
  297. local function UpdateAllySpeed(ally, value: number, increment: boolean?)
  298.     if increment then value += ally.speed end
  299.     ally.speed = value
  300.    
  301.     if not ally.display_speed then
  302.         local buf = buffer.create(8)
  303.         buffer.writeu32(buf, 0, ally.ID)
  304.         buffer.writef32(buf, 4, value)
  305.         remotes.UpdateAllySpeed:FireAllClients(buf)
  306.     end
  307. end
  308.  
  309. local function OverwriteAllySpeed(ally, value: number?, increment: boolean?)
  310.     local buf = buffer.create(8)
  311.     buffer.writeu32(buf, 0, ally.ID)
  312.  
  313.     if value then
  314.         if increment then
  315.             local displaySpeed = ally.display_speed
  316.             if displaySpeed then
  317.                 value += displaySpeed
  318.             end
  319.         end
  320.        
  321.         ally.display_speed = value
  322.         buffer.writef32(buf, 4, value)
  323.     else
  324.         ally.display_speed = nil
  325.         buffer.writef32(buf, 4, ally.speed)
  326.     end
  327.  
  328.     remotes.UpdateAllySpeed:FireAllClients(buf)
  329. end
  330.  
  331. return {
  332.     GetAllyCount = GetAllyCount,
  333.     GetRandomAlly = GetRandomAlly,
  334.     GetAlliesInRange = GetAlliesInRange,
  335.     GetAlliesInRange2D = GetAlliesInRange2D,
  336.     GetAllAllies = GetAllAllies,
  337.     UpdateAllySpeed = UpdateAllySpeed,
  338.     OverwriteAllySpeed = OverwriteAllySpeed,
  339.    
  340.     DamageAlly = DamageAlly,
  341.     AddAlly = AddAlly,
  342.     RemoveAlly = RemoveAlly,
  343.    
  344.     allies = allies
  345. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement