Advertisement
RedDeadlyCreeper

HVAP

Jul 14th, 2018
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.74 KB | None | 0 0
  1.  
  2. AddCSLuaFile()
  3.  
  4. ACF.AmmoBlacklist.HVAP = { "MO", "SL", "GL", "HW", "MG", "SC", "BOMB" , "GBU", "ASM", "AAM", "SAM", "UAR", "POD", "FFAR","RAC", "HRAC", "AC"} -- 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 = "High-Velocity Armor Piercing (HVAP)" --Human readable name
  10. Round.model = "models/munitions/dart_100mm.mdl" --Shell flight model
  11. Round.desc = "A soft projectile that contains a heavy tungsten core, penetrates and does a lot more damage then SABOT but has horrible drag charecteristics"
  12. Round.netid = 11 --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 == "SA" then
  38. Data.MinCalMult = 0.25
  39. Data.MaxCalMult = 0.5
  40. Data.PenModifier = 2
  41. Data.Ricochet = 50
  42. elseif GunClass == "C" then
  43. Data.MinCalMult = 0.25
  44. Data.MaxCalMult = 0.5
  45. Data.PenModifier = 2
  46. Data.Ricochet = 55
  47. else
  48. Data.MinCalMult = 0.25
  49. Data.MaxCalMult = 0.5
  50. Data.PenModifier = 2
  51. Data.Ricochet = 85
  52. end
  53.  
  54. Data.SCalMult = PlayerData["Data5"]
  55. Data.SubFrAera = Data.FrAera * math.min(PlayerData.Data5,Data.MaxCalMult)^2
  56. Data.ProjMass = Data.SubFrAera * (Data.ProjLength*7.9/1000) * 2.5 + (Data.FrAera - Data.SubFrAera) * (Data.ProjLength*7.9/3000) --Volume of the projectile as a cylinder * density of steel
  57. Data.ShovePower = 0.2
  58. Data.PenAera = (Data.PenModifier*Data.SubFrAera)^ACF.PenAreaMod
  59.  
  60. Data.DragCoef = ((Data.FrAera/10000)/Data.ProjMass)
  61. Data.CaliberMod = Data.Caliber*math.min(PlayerData.Data5,Data.MaxCalMult)
  62. Data.LimitVel = 900 --Most efficient penetration speed in m/s
  63. Data.KETransfert = 0.2 --Kinetic energy transfert to the target for movement purposes
  64. Data.MuzzleVel = ACF_MuzzleVelocity( Data.PropMass*0.5, Data.ProjMass*2.5, Data.Caliber )
  65. Data.BoomPower = Data.PropMass
  66.  
  67. if SERVER then --Only the crates need this part
  68. ServerData.Id = PlayerData.Id
  69. ServerData.Type = PlayerData.Type
  70. return table.Merge(Data,ServerData)
  71. end
  72.  
  73. if CLIENT then --Only tthe GUI needs this part
  74. GUIData = table.Merge(GUIData, Round.getDisplayData(Data))
  75. return table.Merge(Data,GUIData)
  76. end
  77.  
  78. end
  79.  
  80.  
  81. function Round.getDisplayData(Data)
  82. local GUIData = {}
  83. local Energy = ACF_Kinetic( Data.MuzzleVel*39.37 , Data.ProjMass, Data.LimitVel )
  84. GUIData.MaxPen = (Energy.Penetration/Data.PenAera)*ACF.KEtoRHA
  85. return GUIData
  86. end
  87.  
  88.  
  89.  
  90. function Round.network( Crate, BulletData )
  91.  
  92. Crate:SetNWString( "AmmoType", "HVAP" )
  93. Crate:SetNWString( "AmmoID", BulletData.Id )
  94. Crate:SetNWFloat( "Caliber", BulletData.Caliber )
  95. Crate:SetNWFloat( "ProjMass", BulletData.ProjMass )
  96. Crate:SetNWFloat( "PropMass", BulletData.PropMass )
  97. Crate:SetNWFloat( "DragCoef", BulletData.DragCoef )
  98. Crate:SetNWFloat( "MuzzleVel", BulletData.MuzzleVel )
  99. Crate:SetNWFloat( "Tracer", BulletData.Tracer )
  100.  
  101. end
  102.  
  103. function Round.cratetxt( BulletData )
  104.  
  105. --local FrAera = BulletData.FrAera
  106. local DData = Round.getDisplayData(BulletData)
  107.  
  108. --fakeent.ACF.Armour = DData.MaxPen or 0
  109. --fakepen.Penetration = (DData.MaxPen * FrAera) / ACF.KEtoRHA
  110. --local fakepen = ACF_Kinetic( BulletData.SlugMV*39.37 , BulletData.SlugMass, 9999999 )
  111. --local MaxHP = ACF_CalcDamage( fakeent , fakepen , FrAera , 0 )
  112.  
  113. --[[
  114. local TotalMass = BulletData.ProjMass + BulletData.PropMass
  115. local MassUnit
  116.  
  117. if TotalMass < 0.1 then
  118. TotalMass = TotalMass * 1000
  119. MassUnit = " g"
  120. else
  121. MassUnit = " kg"
  122. end
  123. ]]--
  124.  
  125. local str =
  126. {
  127. --"Cartridge Mass: ", math.Round(TotalMass, 2), MassUnit, "\n",
  128. "Muzzle Velocity: ", math.Round(BulletData.MuzzleVel, 1), " m/s\n",
  129. "Max Penetration: ", math.floor(DData.MaxPen), " mm"
  130. --"Max Pen. Damage: ", math.Round(MaxHP.Damage, 1), " HP\n",
  131. }
  132.  
  133. return table.concat(str)
  134.  
  135. end
  136.  
  137. function Round.propimpact( Index, Bullet, Target, HitNormal, HitPos, Bone )
  138.  
  139. if ACF_Check( Target ) then
  140.  
  141. local Speed = Bullet.Flight:Length() / ACF.VelScale
  142. local Energy = ACF_Kinetic( Speed , Bullet.ProjMass, Bullet.LimitVel )
  143. local HitRes = ACF_RoundImpact( Bullet, Speed, Energy, Target, HitPos, HitNormal , Bone )
  144.  
  145. if HitRes.Overkill > 0 then
  146. table.insert( Bullet.Filter , Target ) --"Penetrate" (Ingoring the prop for the retry trace)
  147. ACF_Spall( HitPos , Bullet.Flight , Bullet.Filter , Energy.Kinetic*HitRes.Loss , Bullet.Caliber , Target.ACF.Armour , Bullet.Owner ) --Do some spalling
  148. Bullet.Flight = Bullet.Flight:GetNormalized() * (Energy.Kinetic*(1-HitRes.Loss)*2000/Bullet.ProjMass)^0.5 * 39.37
  149. return "Penetrated"
  150. elseif HitRes.Ricochet then
  151. return "Ricochet"
  152. else
  153. return false
  154. end
  155. else
  156. table.insert( Bullet.Filter , Target )
  157. return "Penetrated" end
  158.  
  159. end
  160.  
  161. function Round.worldimpact( Index, Bullet, HitPos, HitNormal )
  162.  
  163. local Energy = ACF_Kinetic( Bullet.Flight:Length() / ACF.VelScale, Bullet.ProjMass, Bullet.LimitVel )
  164. local HitRes = ACF_PenetrateGround( Bullet, Energy, HitPos, HitNormal )
  165. if HitRes.Penetrated then
  166. return "Penetrated"
  167. elseif HitRes.Ricochet then
  168. return "Ricochet"
  169. else
  170. return false
  171. end
  172.  
  173. end
  174.  
  175. function Round.endflight( Index, Bullet, HitPos )
  176.  
  177. ACF_RemoveBullet( Index )
  178.  
  179. end
  180.  
  181. -- Bullet stops here
  182. function Round.endeffect( Effect, Bullet )
  183.  
  184. local Spall = EffectData()
  185. Spall:SetEntity( Bullet.Crate )
  186. Spall:SetOrigin( Bullet.SimPos )
  187. Spall:SetNormal( (Bullet.SimFlight):GetNormalized() )
  188. Spall:SetScale( Bullet.SimFlight:Length() )
  189. Spall:SetMagnitude( Bullet.RoundMass )
  190. util.Effect( "ACF_AP_Impact", Spall )
  191.  
  192. end
  193.  
  194. -- Bullet penetrated something
  195. function Round.pierceeffect( Effect, Bullet )
  196.  
  197. local Spall = EffectData()
  198. Spall:SetEntity( Bullet.Crate )
  199. Spall:SetOrigin( Bullet.SimPos )
  200. Spall:SetNormal( (Bullet.SimFlight):GetNormalized() )
  201. Spall:SetScale( Bullet.SimFlight:Length() )
  202. Spall:SetMagnitude( Bullet.RoundMass )
  203. util.Effect( "ACF_AP_Penetration", Spall )
  204.  
  205. end
  206.  
  207. -- Bullet ricocheted off something
  208. function Round.ricocheteffect( Effect, Bullet )
  209.  
  210. local Spall = EffectData()
  211. Spall:SetEntity( Bullet.Crate )
  212. Spall:SetOrigin( Bullet.SimPos )
  213. Spall:SetNormal( (Bullet.SimFlight):GetNormalized() )
  214. Spall:SetScale( Bullet.SimFlight:Length() )
  215. Spall:SetMagnitude( Bullet.RoundMass )
  216. util.Effect( "ACF_AP_Ricochet", Spall )
  217.  
  218. end
  219.  
  220. function Round.guicreate( Panel, Table )
  221.  
  222. acfmenupanel:AmmoSelect( ACF.AmmoBlacklist.HVAP )
  223.  
  224. acfmenupanel:CPanelText("BonusDisplay", "")
  225.  
  226. acfmenupanel:CPanelText("Desc", "") --Description (Name, Desc)
  227. acfmenupanel:CPanelText("LengthDisplay", "") --Total round length (Name, Desc)
  228.  
  229. acfmenupanel:AmmoSlider("PropLength",0,0,1000,3, "Propellant Length", "") --Propellant Length Slider (Name, Value, Min, Max, Decimals, Title, Desc)
  230. acfmenupanel:AmmoSlider("ProjLength",0,0,1000,3, "Projectile Length", "") --Projectile Length Slider (Name, Value, Min, Max, Decimals, Title, Desc)
  231. acfmenupanel:AmmoSlider("SCalMult",0,0,1000,2, "Subcaliber Size Multiplier", "")--Subcaliber Slider (Name, Value, Min, Max, Decimals, Title, Desc)
  232.  
  233. acfmenupanel:CPanelText("VelocityDisplay", "") --Proj muzzle velocity (Name, Desc)
  234. --acfmenupanel:CPanelText("RicoDisplay", "") --estimated rico chance
  235. acfmenupanel:CPanelText("PenetrationDisplay", "") --Proj muzzle penetration (Name, Desc)
  236.  
  237. Round.guiupdate( Panel, Table )
  238.  
  239. end
  240.  
  241. function Round.guiupdate( Panel, Table )
  242.  
  243. local PlayerData = {}
  244. PlayerData.Id = acfmenupanel.AmmoData.Data.id --AmmoSelect GUI
  245. PlayerData.Type = "HVAP" --Hardcoded, match ACFRoundTypes table index
  246. PlayerData.PropLength = acfmenupanel.AmmoData.PropLength --PropLength slider
  247. PlayerData.ProjLength = acfmenupanel.AmmoData.ProjLength --ProjLength slider
  248. PlayerData.Data5 = acfmenupanel.AmmoData.SCalMult
  249. PlayerData.Data10 = 0
  250. local Data = Round.convert( Panel, PlayerData )
  251.  
  252. RunConsoleCommand( "acfmenu_data1", acfmenupanel.AmmoData.Data.id )
  253. RunConsoleCommand( "acfmenu_data2", PlayerData.Type )
  254. RunConsoleCommand( "acfmenu_data3", Data.PropLength ) --For Gun ammo, Data3 should always be Propellant
  255. RunConsoleCommand( "acfmenu_data4", Data.ProjLength ) --And Data4 total round mass
  256. RunConsoleCommand( "acfmenu_data5", Data.SCalMult )
  257. RunConsoleCommand( "acfmenu_data10", 0 )
  258.  
  259. local vol = ACF.Weapons.Ammo[acfmenupanel.AmmoData["Id"]].volume
  260. local CapMul = (vol > 46000) and ((math.log(vol*0.00066)/math.log(2)-4)*0.125+1) or 1
  261. local RoFMul = (vol > 46000) and (1-(math.log(vol*0.00066)/math.log(2)-4)*0.05) or 1
  262. local Cap = math.floor(CapMul * vol * 0.11 * ACF.AmmoMod * 16.38 / Data.RoundVolume)
  263.  
  264. acfmenupanel:CPanelText("BonusDisplay", "Crate info: +"..(math.Round((CapMul-1)*100,1)).."% capacity, +"..(math.Round((RoFMul-1)*-100,1)).."% RoF\nContains "..Cap.." rounds")
  265.  
  266. 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)
  267. 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)
  268.  
  269. 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)
  270.  
  271.  
  272. acfmenupanel:CPanelText("Desc", ACF.RoundTypes[PlayerData.Type].desc) --Description (Name, Desc)
  273. acfmenupanel:CPanelText("LengthDisplay", "Round Length : "..(math.floor((Data.PropLength+Data.ProjLength)*100)/100).."/"..(Data.MaxTotalLength).." cm") --Total round length (Name, Desc)
  274. acfmenupanel:CPanelText("VelocityDisplay", "Muzzle Velocity : "..math.floor(Data.MuzzleVel*ACF.VelScale).." m\\s") --Proj muzzle velocity (Name, Desc)
  275.  
  276. --local RicoAngs = ACF_RicoProbability( Data.Ricochet, Data.MuzzleVel*ACF.VelScale )
  277. --acfmenupanel:CPanelText("RicoDisplay", "Ricochet probability vs impact angle:\n".." 0% @ "..RicoAngs.Min.." degrees\n 50% @ "..RicoAngs.Mean.." degrees\n100% @ "..RicoAngs.Max.." degrees")
  278.  
  279. local R1V, R1P = ACF_PenRanging( Data.MuzzleVel, Data.DragCoef, Data.ProjMass, Data.PenAera, Data.LimitVel, 300 )
  280. local R2V, R2P = ACF_PenRanging( Data.MuzzleVel, Data.DragCoef, Data.ProjMass, Data.PenAera, Data.LimitVel, 800 )
  281.  
  282. 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)
  283.  
  284.  
  285. end
  286.  
  287. list.Set( "ACFRoundTypes", "HVAP", Round ) --Set the round properties
  288. list.Set( "ACFIdRounds", Round.netid, "HVAP" ) --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