Advertisement
RedDeadlyCreeper

APDS ammo

Jul 14th, 2018
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.29 KB | None | 0 0
  1.  
  2. AddCSLuaFile()
  3.  
  4. ACF.AmmoBlacklist.APDS = { "ATR", "MO", "RM", "SL", "GL", "HW", "MG", "SC", "BOMB" , "GBU", "ASM", "AAM", "SAM", "UAR", "POD", "FFAR"} -- Yes, I know I left the flare launcher out, deal with it
  5.  
  6. local Round = {}
  7.  
  8. Round.type = "Ammo" --Tells the spawn menu what entity to spawn
  9. Round.name = "Armour Piercing Discarding Sabot (APDS)" --Human readable name
  10. Round.model = "models/munitions/dart_100mm.mdl" --Shell flight model
  11. Round.desc = "A shell that contains a subcaliber round, dedicated to penetrating heavy armour, if fired out a smoothbore then the round is fin stabilized and recieves an accuracy boost and richochets less"
  12. Round.netid = 9 --Unique ammotype ID for network transmission
  13.  
  14. function Round.create( Gun, BulletData )
  15.  
  16. ACF_CreateBullet( BulletData )
  17.  
  18. end
  19.  
  20. -- Function to convert the player's slider data into the complete round data
  21. function Round.convert( Crate, PlayerData )
  22.  
  23. local Data = {}
  24. local ServerData = {}
  25. local GUIData = {}
  26.  
  27. if not PlayerData.PropLength then PlayerData.PropLength = 0 end
  28. if not PlayerData.ProjLength then PlayerData.ProjLength = 0 end
  29. if not PlayerData.SCalMult then PlayerData.SCalMult = 0.5 end
  30. if not PlayerData["Data5"] then PlayerData["Data5"] = 0.5 end --caliber in mm count
  31. if not PlayerData.Data10 then PlayerData.Data10 = 0 end
  32.  
  33. PlayerData, Data, ServerData, GUIData = ACF_RoundBaseGunpowder( PlayerData, Data, ServerData, GUIData )
  34.  
  35. local GunClass = ACF.Weapons["Guns"][(Data["Id"] or PlayerData["Id"])]["gunclass"]
  36.  
  37. if GunClass == "AC" then
  38. Data.MinCalMult = 0.35
  39. Data.MaxCalMult = 1.0
  40. Data.PenModifier = 2 -- Autocannons are puny anyways
  41. Data.VelModifier = 1.6
  42. Data.Ricochet = 55
  43. elseif GunClass == "RAC" then
  44. Data.MinCalMult = 0.5
  45. Data.MaxCalMult = 1.0
  46. Data.PenModifier = 1.8
  47. Data.VelModifier = 1.7
  48. Data.Ricochet = 50
  49. elseif GunClass == "HRAC" then
  50. Data.MinCalMult = 0.5
  51. Data.MaxCalMult = 1.0
  52. Data.PenModifier = 1.9
  53. Data.VelModifier = 1.7
  54. Data.Ricochet = 50
  55. elseif GunClass == "SA" then
  56. Data.MinCalMult = 0.3
  57. Data.MaxCalMult = 1.0
  58. Data.PenModifier = 2
  59. Data.VelModifier = 1.6
  60. Data.Ricochet = 60
  61. elseif GunClass == "C" then
  62. Data.MinCalMult = 0.28
  63. Data.MaxCalMult = 1.0
  64. Data.PenModifier = 1.35
  65. Data.VelModifier = 1
  66. Data.Ricochet = 62
  67. else
  68. Data.MinCalMult = 0.25
  69. Data.MaxCalMult = 1.0
  70. Data.PenModifier = 1
  71. Data.VelModifier = 1
  72. Data.Ricochet = 68
  73. end
  74.  
  75. Data.SCalMult = PlayerData["Data5"]
  76. Data.SubFrAera = Data.FrAera * math.min(PlayerData.Data5,Data.MaxCalMult)^2
  77. Data.ProjMass = Data.SubFrAera * (Data.ProjLength*7.9/1000) * 2.5 --Volume of the projectile as a cylinder * density of steel
  78. Data.ShovePower = 0.2
  79. Data.PenAera = (Data.PenModifier*Data.SubFrAera)^ACF.PenAreaMod
  80.  
  81. Data.DragCoef = ((Data.SubFrAera/10000)/Data.ProjMass)
  82. Data.CaliberMod = Data.Caliber*math.min(PlayerData.Data5,Data.MaxCalMult)
  83. Data.LimitVel = 1000 --Most efficient penetration speed in m/s
  84. Data.KETransfert = 0.2 --Kinetic energy transfert to the target for movement purposes
  85. Data.MuzzleVel = ACF_MuzzleVelocity( Data.PropMass * 0.5 , Data.ProjMass*2.5, Data.Caliber )* Data.VelModifier
  86. Data.BoomPower = Data.PropMass
  87.  
  88. if SERVER then --Only the crates need this part
  89. ServerData.Id = PlayerData.Id
  90. ServerData.Type = PlayerData.Type
  91. return table.Merge(Data,ServerData)
  92. end
  93.  
  94. if CLIENT then --Only tthe GUI needs this part
  95. GUIData = table.Merge(GUIData, Round.getDisplayData(Data))
  96. return table.Merge(Data,GUIData)
  97. end
  98.  
  99. end
  100.  
  101.  
  102. function Round.getDisplayData(Data)
  103. local GUIData = {}
  104. local Energy = ACF_Kinetic( Data.MuzzleVel*39.37 , Data.ProjMass, Data.LimitVel )
  105. GUIData.MaxPen = (Energy.Penetration/Data.PenAera)*ACF.KEtoRHA
  106. return GUIData
  107. end
  108.  
  109.  
  110.  
  111. function Round.network( Crate, BulletData )
  112.  
  113. Crate:SetNWString( "AmmoType", "APDS" )
  114. Crate:SetNWString( "AmmoID", BulletData.Id )
  115. Crate:SetNWFloat( "Caliber", BulletData.Caliber )
  116. Crate:SetNWFloat( "ProjMass", BulletData.ProjMass )
  117. Crate:SetNWFloat( "PropMass", BulletData.PropMass )
  118. Crate:SetNWFloat( "DragCoef", BulletData.DragCoef )
  119. Crate:SetNWFloat( "MuzzleVel", BulletData.MuzzleVel )
  120. Crate:SetNWFloat( "Tracer", BulletData.Tracer )
  121.  
  122. end
  123.  
  124. function Round.cratetxt( BulletData )
  125.  
  126. --local FrAera = BulletData.FrAera
  127. local DData = Round.getDisplayData(BulletData)
  128.  
  129. --fakeent.ACF.Armour = DData.MaxPen or 0
  130. --fakepen.Penetration = (DData.MaxPen * FrAera) / ACF.KEtoRHA
  131. --local fakepen = ACF_Kinetic( BulletData.SlugMV*39.37 , BulletData.SlugMass, 9999999 )
  132. --local MaxHP = ACF_CalcDamage( fakeent , fakepen , FrAera , 0 )
  133.  
  134. --[[
  135. local TotalMass = BulletData.ProjMass + BulletData.PropMass
  136. local MassUnit
  137.  
  138. if TotalMass < 0.1 then
  139. TotalMass = TotalMass * 1000
  140. MassUnit = " g"
  141. else
  142. MassUnit = " kg"
  143. end
  144. ]]--
  145.  
  146. local str =
  147. {
  148. --"Cartridge Mass: ", math.Round(TotalMass, 2), MassUnit, "\n",
  149. "Muzzle Velocity: ", math.Round(BulletData.MuzzleVel, 1), " m/s\n",
  150. "Max Penetration: ", math.floor(DData.MaxPen), " mm"
  151. --"Max Pen. Damage: ", math.Round(MaxHP.Damage, 1), " HP\n",
  152. }
  153.  
  154. return table.concat(str)
  155.  
  156. end
  157.  
  158. function Round.propimpact( Index, Bullet, Target, HitNormal, HitPos, Bone )
  159.  
  160. if ACF_Check( Target ) then
  161.  
  162. local Speed = Bullet.Flight:Length() / ACF.VelScale
  163. local Energy = ACF_Kinetic( Speed , Bullet.ProjMass, Bullet.LimitVel )
  164. local HitRes = ACF_RoundImpact( Bullet, Speed, Energy, Target, HitPos, HitNormal , Bone )
  165.  
  166. if HitRes.Overkill > 0 then
  167. table.insert( Bullet.Filter , Target ) --"Penetrate" (Ingoring the prop for the retry trace)
  168. ACF_Spall( HitPos , Bullet.Flight , Bullet.Filter , Energy.Kinetic*HitRes.Loss , Bullet.Caliber , Target.ACF.Armour , Bullet.Owner ) --Do some spalling
  169. Bullet.Flight = Bullet.Flight:GetNormalized() * (Energy.Kinetic*(1-HitRes.Loss)*2000/Bullet.ProjMass)^0.5 * 39.37
  170. return "Penetrated"
  171. elseif HitRes.Ricochet then
  172. return "Ricochet"
  173. else
  174. return false
  175. end
  176. else
  177. table.insert( Bullet.Filter , Target )
  178. return "Penetrated" end
  179.  
  180. end
  181.  
  182. function Round.worldimpact( Index, Bullet, HitPos, HitNormal )
  183.  
  184. local Energy = ACF_Kinetic( Bullet.Flight:Length() / ACF.VelScale, Bullet.ProjMass, Bullet.LimitVel )
  185. local HitRes = ACF_PenetrateGround( Bullet, Energy, HitPos, HitNormal )
  186. if HitRes.Penetrated then
  187. return "Penetrated"
  188. elseif HitRes.Ricochet then
  189. return "Ricochet"
  190. else
  191. return false
  192. end
  193.  
  194. end
  195.  
  196. function Round.endflight( Index, Bullet, HitPos )
  197.  
  198. ACF_RemoveBullet( Index )
  199.  
  200. end
  201.  
  202. -- Bullet stops here
  203. function Round.endeffect( Effect, Bullet )
  204.  
  205. local Spall = EffectData()
  206. Spall:SetEntity( Bullet.Crate )
  207. Spall:SetOrigin( Bullet.SimPos )
  208. Spall:SetNormal( (Bullet.SimFlight):GetNormalized() )
  209. Spall:SetScale( Bullet.SimFlight:Length() )
  210. Spall:SetMagnitude( Bullet.RoundMass )
  211. util.Effect( "ACF_AP_Impact", Spall )
  212.  
  213. end
  214.  
  215. -- Bullet penetrated something
  216. function Round.pierceeffect( Effect, Bullet )
  217.  
  218. local Spall = EffectData()
  219. Spall:SetEntity( Bullet.Crate )
  220. Spall:SetOrigin( Bullet.SimPos )
  221. Spall:SetNormal( (Bullet.SimFlight):GetNormalized() )
  222. Spall:SetScale( Bullet.SimFlight:Length() )
  223. Spall:SetMagnitude( Bullet.RoundMass )
  224. util.Effect( "ACF_AP_Penetration", Spall )
  225.  
  226. end
  227.  
  228. -- Bullet ricocheted off something
  229. function Round.ricocheteffect( Effect, Bullet )
  230.  
  231. local Spall = EffectData()
  232. Spall:SetEntity( Bullet.Crate )
  233. Spall:SetOrigin( Bullet.SimPos )
  234. Spall:SetNormal( (Bullet.SimFlight):GetNormalized() )
  235. Spall:SetScale( Bullet.SimFlight:Length() )
  236. Spall:SetMagnitude( Bullet.RoundMass )
  237. util.Effect( "ACF_AP_Ricochet", Spall )
  238.  
  239. end
  240.  
  241. function Round.guicreate( Panel, Table )
  242.  
  243. acfmenupanel:AmmoSelect( ACF.AmmoBlacklist.APDS )
  244.  
  245. acfmenupanel:CPanelText("BonusDisplay", "")
  246.  
  247. acfmenupanel:CPanelText("Desc", "") --Description (Name, Desc)
  248. acfmenupanel:CPanelText("LengthDisplay", "") --Total round length (Name, Desc)
  249.  
  250. acfmenupanel:AmmoSlider("PropLength",0,0,1000,3, "Propellant Length", "") --Propellant Length Slider (Name, Value, Min, Max, Decimals, Title, Desc)
  251. acfmenupanel:AmmoSlider("ProjLength",0,0,1000,3, "Projectile Length", "") --Projectile Length Slider (Name, Value, Min, Max, Decimals, Title, Desc)
  252. acfmenupanel:AmmoSlider("SCalMult",0,0,1000,2, "Subcaliber Size Multiplier", "")--Subcaliber Slider (Name, Value, Min, Max, Decimals, Title, Desc)
  253.  
  254. acfmenupanel:CPanelText("VelocityDisplay", "") --Proj muzzle velocity (Name, Desc)
  255. --acfmenupanel:CPanelText("RicoDisplay", "") --estimated rico chance
  256. acfmenupanel:CPanelText("PenetrationDisplay", "") --Proj muzzle penetration (Name, Desc)
  257.  
  258. Round.guiupdate( Panel, Table )
  259.  
  260. end
  261.  
  262. function Round.guiupdate( Panel, Table )
  263.  
  264. local PlayerData = {}
  265. PlayerData.Id = acfmenupanel.AmmoData.Data.id --AmmoSelect GUI
  266. PlayerData.Type = "APDS" --Hardcoded, match ACFRoundTypes table index
  267. PlayerData.PropLength = acfmenupanel.AmmoData.PropLength --PropLength slider
  268. PlayerData.ProjLength = acfmenupanel.AmmoData.ProjLength --ProjLength slider
  269. PlayerData.Data5 = acfmenupanel.AmmoData.SCalMult
  270. PlayerData.Data10 = 0
  271. local Data = Round.convert( Panel, PlayerData )
  272.  
  273. RunConsoleCommand( "acfmenu_data1", acfmenupanel.AmmoData.Data.id )
  274. RunConsoleCommand( "acfmenu_data2", PlayerData.Type )
  275. RunConsoleCommand( "acfmenu_data3", Data.PropLength ) --For Gun ammo, Data3 should always be Propellant
  276. RunConsoleCommand( "acfmenu_data4", Data.ProjLength ) --And Data4 total round mass
  277. RunConsoleCommand( "acfmenu_data5", Data.SCalMult )
  278. RunConsoleCommand( "acfmenu_data10", 0 )
  279.  
  280. local vol = ACF.Weapons.Ammo[acfmenupanel.AmmoData["Id"]].volume
  281. local CapMul = (vol > 46000) and ((math.log(vol*0.00066)/math.log(2)-4)*0.125+1) or 1
  282. local RoFMul = (vol > 46000) and (1-(math.log(vol*0.00066)/math.log(2)-4)*0.05) or 1
  283. local Cap = math.floor(CapMul * vol * 0.11 * ACF.AmmoMod * 16.38 / Data.RoundVolume)
  284.  
  285. acfmenupanel:CPanelText("BonusDisplay", "Crate info: +"..(math.Round((CapMul-1)*100,1)).."% capacity, +"..(math.Round((RoFMul-1)*-100,1)).."% RoF\nContains "..Cap.." rounds")
  286.  
  287. acfmenupanel:AmmoSlider("PropLength",Data.PropLength,Data.MinPropLength,Data.MaxTotalLength,3, "Propellant Length", "Propellant Mass : "..(math.floor(Data.PropMass*1000)).." g" ) --Propellant Length Slider (Name, Min, Max, Decimals, Title, Desc)
  288. acfmenupanel:AmmoSlider("ProjLength",Data.ProjLength,Data.MinProjLength,Data.MaxTotalLength,3, "Projectile Length", "Projectile Mass : "..(math.floor(Data.ProjMass*1000)).." g") --Projectile Length Slider (Name, Min, Max, Decimals, Title, Desc)
  289.  
  290. acfmenupanel:AmmoSlider("SCalMult",Data.SCalMult,Data.MinCalMult,Data.MaxCalMult,2, "Subcaliber Size Multiplier", "Caliber : "..math.floor(Data.Caliber * math.min(PlayerData.Data5,Data.MaxCalMult)*10).." mm")--Subcaliber round slider (Name, Min, Max, Decimals, Title, Desc)
  291.  
  292.  
  293. acfmenupanel:CPanelText("Desc", ACF.RoundTypes[PlayerData.Type].desc) --Description (Name, Desc)
  294. acfmenupanel:CPanelText("LengthDisplay", "Round Length : "..(math.floor((Data.PropLength+Data.ProjLength)*100)/100).."/"..(Data.MaxTotalLength).." cm") --Total round length (Name, Desc)
  295. acfmenupanel:CPanelText("VelocityDisplay", "Muzzle Velocity : "..math.floor(Data.MuzzleVel*ACF.VelScale).." m\\s") --Proj muzzle velocity (Name, Desc)
  296.  
  297. --local RicoAngs = ACF_RicoProbability( Data.Ricochet, Data.MuzzleVel*ACF.VelScale )
  298. --acfmenupanel:CPanelText("RicoDisplay", "Ricochet probability vs impact angle:\n".." 0% @ "..RicoAngs.Min.." degrees\n 50% @ "..RicoAngs.Mean.." degrees\n100% @ "..RicoAngs.Max.." degrees")
  299.  
  300. local R1V, R1P = ACF_PenRanging( Data.MuzzleVel, Data.DragCoef, Data.ProjMass, Data.PenAera, Data.LimitVel, 300 )
  301. local R2V, R2P = ACF_PenRanging( Data.MuzzleVel, Data.DragCoef, Data.ProjMass, Data.PenAera, Data.LimitVel, 800 )
  302.  
  303. acfmenupanel:CPanelText("PenetrationDisplay", "Maximum Penetration : "..math.floor(Data.MaxPen).." mm RHA\n\n300m pen: "..math.Round(R1P,0).."mm @ "..math.Round(R1V,0).." m\\s\n800m pen: "..math.Round(R2P,0).."mm @ "..math.Round(R2V,0).." m\\s\n\nThe range data is an approximation and may not be entirely accurate.") --Proj muzzle penetration (Name, Desc)
  304.  
  305.  
  306. end
  307.  
  308. list.Set( "ACFRoundTypes", "APDS", Round ) --Set the round properties
  309. list.Set( "ACFIdRounds", Round.netid, "APDS" ) --Index must equal the ID entry in the table above, Data must equal the index of the table above
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement