Advertisement
WeltEnSTurm

Untitled

Sep 8th, 2010
394
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 26.24 KB | None | 0 0
  1.  
  2. include("shared.lua")
  3. include("entities/base_wire_entity/init.lua")
  4. AddCSLuaFile("cl_init.lua")
  5. AddCSLuaFile("shared.lua")
  6.  
  7. local NULLVEC=Vector(0,0,0)
  8.  
  9. WAC.Helicopter.CVars={
  10.     RPM=CreateConVar("wac_heli_rpmneeded", 2500, {FCVAR_REPLICATED, FCVAR_ARCHIVE}),
  11.     SSpeed=CreateConVar("wac_heli_startspeed", 1, {FCVAR_REPLICATED, FCVAR_ARCHIVE}),
  12.     PHM=CreateConVar("wac_heli_phmul", 1, {FCVAR_REPLICATED, FCVAR_ARCHIVE}),
  13. }
  14.  
  15. WAC.Hook("SetPlayerAnimation", "SetHeliChairAnim", function(pl, anim)
  16.      if pl:InVehicle() then
  17.      local Veh = pl:GetVehicle()
  18.         if string.find(Veh:GetModel(), "models/nova/airboat_seat") then
  19.             local seq = pl:LookupSequence("sit")   
  20.             pl:SetPlaybackRate(1.0)
  21.             pl:ResetSequence(seq)
  22.             pl:SetCycle(0)
  23.             return true
  24.         end
  25.     end
  26. end)
  27.  
  28. function ENT:UpdateTransmitState() return TRANSMIT_ALWAYS end
  29.  
  30. ENT.IgnoreDamage    = true
  31. ENT.wac_ignore      = true
  32. ENT.Model           = nil
  33. ENT.RotorPhModel    = nil
  34. ENT.RotorModel      = nil
  35. ENT.BackRotorModel= nil
  36. ENT.UsePhysRotor    = false
  37. ENT.Submersible = false
  38. ENT.CrRotorWash = false
  39. ENT.RotorWidth      = 200
  40. ENT.TopRotorDir = -1
  41. ENT.BackRotorDir    = -1
  42. ENT.TopRotorPos = Vector(0,0,50)
  43. ENT.BackRotorPos    = Vector(-185,-3,13)
  44. ENT.EngineForce = 20
  45. ENT.BrakeMul        = 1
  46. ENT.AngBrakeMul = 0.01
  47. ENT.Weight          = 1000
  48. ENT.SeatSwitcherPos= Vector(0,0,50)
  49. ENT.MaxEnterDistance= 50
  50.  
  51. function ENT:Initialize()
  52.     self.Entity:SetModel(self.Model)
  53.     self.Entity:PhysicsInit(SOLID_VPHYSICS)
  54.     self.Entity:SetMoveType(MOVETYPE_VPHYSICS)
  55.     self.Entity:SetSolid(SOLID_VPHYSICS)
  56.     self.Phys = self.Entity:GetPhysicsObject()
  57.     if self.Phys:IsValid() then
  58.         self.Phys:SetMass(self.Weight)
  59.         self.Phys:Wake()
  60.     end
  61.     self:AddRotor()
  62.     self:AddSeats()
  63.     self:AddSounds()
  64.     self:AddWireInputs()
  65.    
  66.     self.UpdateSecond = 0
  67.     self.wac_seatswitch = true
  68.     self.StartTime = 0
  69.     self.HoverTime=0
  70.     self.engineHealth = 100
  71.     self.pitchMul = 0
  72.     self.yawMul = 0
  73.     self.rollMul = 0
  74.     self.startMul = 0
  75.     self.upMul = 0
  76.     self:SetNWFloat("health", 100)
  77.     self.LastActivated = 0
  78.     self.NextWepSwitch = 0
  79.     self.NextCamSwitch = 0
  80.     self.engineStart = 0
  81.     self.LastPhys=0
  82.     self.Passenger={}
  83. end
  84.  
  85. function ENT:AddWireInputs()
  86.     Wire_CreateInputs(self,{"Pitch","Yaw","Roll","Start","Thrust","Fire","NextWeapon"})
  87. end
  88.  
  89. function ENT:TriggerInput(n,v)
  90.     if n=="Pitch" then
  91.         --self.yawMul
  92.     end
  93. end
  94.  
  95. function ENT:AddRotor()
  96.     if self.UsePhysRotor then
  97.         self.TopRotor = ents.Create("prop_physics")
  98.         self.TopRotor:SetModel("models/props_junk/sawblade001a.mdl")
  99.         self.TopRotor:SetPos(self:LocalToWorld(self.TopRotorPos))
  100.         self.TopRotor:SetOwner(self.Owner)
  101.         self.TopRotor:Spawn()
  102.         self.TopRotor:SetNotSolid(true)
  103.         self.TopRotor.Phys = self.TopRotor:GetPhysicsObject()
  104.         self.TopRotor.Phys:EnableGravity(false)
  105.         self.TopRotor.Phys:SetMass(5)
  106.         self.TopRotor:SetColor(Color(0,0,0,0))
  107.         self.TopRotor.fHealth = 100
  108.         self.TopRotor.wac_ignore = true
  109.         if self.RotorModel then
  110.             local e = ents.Create("prop_physics")
  111.             e:SetModel(self.RotorModel)
  112.             e:SetPos(self:LocalToWorld(self.TopRotorPos))
  113.             e:Spawn()
  114.             e:SetOwner(self.Owner)
  115.             e:SetNotSolid(true)
  116.             e:SetParent(self.TopRotor)
  117.             e.wac_ignore = true
  118.         end
  119.         self.BackRotor=self:AddBackRotor()
  120.         self:SetNWEntity("rotor_rear",self.BackRotor)
  121.         constraint.Axis(self.Entity, self.TopRotor, 0, 0, self.TopRotorPos, Vector(0,0,1),0,0,0.04,1)  
  122.         constraint.Axis(self.Entity, self.BackRotor, 0, 0, self.BackRotorPos, Vector(0,1,0) ,0,0,0.5,1)
  123.     end
  124. end
  125.  
  126. function ENT:AddBackRotor()
  127.     local e=ents.Create("prop_physics")
  128.     e:SetPos(self:LocalToWorld(self.BackRotorPos))
  129.     e:SetModel(self.BackRotorModel)
  130.     e:Spawn()
  131.     e:SetOwner(self.Owner)
  132.     e:SetNWFloat("rotorhealth", 100)
  133.     e.wac_ignore=true
  134.     e.Phys=e:GetPhysicsObject()
  135.     if e.Phys:IsValid() then
  136.         e.Phys:Wake()
  137.         e.Phys:EnableGravity(false)
  138.         e.Phys:EnableDrag(false)
  139.         e.Phys:SetMass(10)
  140.     end
  141.     e.fHealth = 40
  142.     return e
  143. end
  144.  
  145. function ENT:AddSeats()
  146.     self.Seats={}
  147.     local ang=self:GetAngles()
  148.     local e=ents.Create("wac_v_connector")
  149.     e:SetPos(self:LocalToWorld(self.SeatSwitcherPos))
  150.     e:SetColor(0,0,0,0)
  151.     e:Spawn()
  152.     e.wac_ignore = true
  153.     e:SetParent(self.Entity)
  154.     self.SeatSwitcher=e
  155.     for k,v in pairs(self.SeatsT) do
  156.         if type(v)=="table" and v.Pos then
  157.             for _,t in pairs(v.wep) do
  158.                 if type(t)=="table" then
  159.                     if t.Init then t.Init(self,t) end
  160.                 end
  161.             end
  162.             self:SetNWInt("seat_"..k.."_actwep", 1)
  163.             self:SetNWInt("seat_"..k.."_ammo", v.wep[1].Ammo)
  164.             self.Seats[k]=ents.Create("prop_vehicle_prisoner_pod")
  165.             --self.Seats[k]:SetKeyValue("vehiclescript","scripts/vehicles/HeliSeat.txt")    
  166.             self.Seats[k]:SetModel("models/nova/airboat_seat.mdl")
  167.             self.Seats[k]:SetPos(self:LocalToWorld(v.Pos))
  168.             self.Seats[k]:SetAngles(ang+Angle(0,-90,0))
  169.             self.Seats[k]:Spawn()
  170.             self.Seats[k]:SetColor(0,0,0,0)
  171.             self.Seats[k].BigOne = self.Entity
  172.             self.Seats[k].Phys = self.Seats[k]:GetPhysicsObject()
  173.             self.Seats[k].Phys:EnableGravity(true)
  174.             self.Seats[k].Phys:SetMass(1)
  175.             self.Seats[k]:SetNotSolid(true)
  176.             self.Seats[k]:SetParent(self.Entity)
  177.             self.Seats[k].wac_ignore = true
  178.             self.Seats[k]:SetNWEntity("BigOne", self.Entity)
  179.             self.SeatSwitcher:AddVehicle(self.Seats[k])
  180.         end
  181.     end
  182. end
  183.  
  184. function ENT:NextWeapon(t,k,p)
  185.     if t[t.act].DeSelect then t[t.act].DeSelect(self.Entity, t[t.act], p) end
  186.     t.act=(t.act<#t)and(t.act+1)or(1)
  187.     t.NextSelect=CurTime()+0.5
  188.     self:SetNWInt("seat_"..k.."_actwep", t.act)
  189.     self:SetNWFloat("seat_"..k.."_nextshot", t[t.act].NextShoot)
  190.     self:SetNWFloat("seat_"..k.."_lastshot", t[t.act].LastShot)
  191.     self:SetNWFloat("seat_"..k.."_ammo", t[t.act].Ammo)
  192. end
  193.  
  194. function ENT:SeatSwitch(p, s)
  195.     if !self.Seats[s] then return end
  196.     local psngr = self.Seats[s]:GetPassenger()
  197.     if !psngr or !psngr:IsValid() or !psngr:InVehicle() then
  198.         p:ExitVehicle()
  199.         p:EnterVehicle(self.Seats[s])
  200.         self:UpdateSeats()
  201.     end
  202. end
  203.  
  204. function ENT:EjectPassenger(ply,idx,t)
  205.     if ply.LastVehicleEntered and ply.LastVehicleEntered<CurTime() then
  206.         if !idx then
  207.             for k,p in pairs(self.Passenger) do
  208.                 if p==ply then idx=k end
  209.             end
  210.             if !idx then
  211.                 return
  212.             end
  213.         end
  214.         ply.LastVehicleEntered = CurTime()+0.5
  215.         ply:ExitVehicle()
  216.         ply:SetPos(self:LocalToWorld(self.SeatsT[idx].ExitPos))
  217.         ply:SetVelocity(self:GetPhysicsObject():GetVelocity()*0.8)
  218.         self:UpdateSeats()
  219.     end
  220. end
  221.  
  222. function ENT:Use(act, cal)
  223.     if self.Lock then return end
  224.     local crt = CurTime()
  225.     if !act.LastVehicleEntered or act.LastVehicleEntered < crt then
  226.         local d=self.MaxEnterDistance
  227.         local v
  228.         for k,veh in pairs(self.Seats) do
  229.             if veh and veh:IsValid() then
  230.                 local psngr = veh:GetPassenger()
  231.                 if !psngr or !psngr:IsValid() then
  232.                     local dist=veh:GetPos():Distance(util.QuickTrace(act:GetShootPos(),act:GetAimVector()*self.MaxEnterDistance,act).HitPos)
  233.                     if dist<d then
  234.                         d=dist
  235.                         v=veh
  236.                     end
  237.                 end
  238.             end
  239.         end
  240.         if v then
  241.             act.HeliKeysDown={}
  242.             act:EnterVehicle(v)
  243.             act.LastVehicleEntered=crt+0.5     
  244.         end
  245.     end
  246.     self:UpdateSeats()
  247. end
  248.  
  249. function ENT:UpdateSeats()
  250.     for k, veh in pairs(self.Seats) do
  251.         if !veh:IsValid() then return end
  252.         local p = veh:GetPassenger()
  253.         if self.Passenger[k] != p then
  254.             if ValidEntity(self.Passenger[k]) then
  255.                 self.Passenger[k].HeliKeysDown={}
  256.                 self.Passenger[k]:SetNWEntity("BigOne", NULL)
  257.                 --self.Passenger[k]:SetNWInt("wac_passenger_id",0)
  258.                 --self.Passenger[k].wac_passenger_id=0
  259.             end
  260.             self:SetNWEntity("passenger_"..k, p)
  261.             p:SetNWInt("wac_passenger_id",k)
  262.             p.wac_passenger_id=k
  263.             self.Passenger[k]=p
  264.         end
  265.     end
  266. end
  267.  
  268. function ENT:StopAllSounds()
  269.     for k, s in pairs(self.Sounds) do
  270.         s[2] = false
  271.         s[1]:Stop()
  272.     end
  273. end
  274.  
  275. local keyids={
  276.     [WAC_HELI_LEANP]    ={7,8},
  277.     [WAC_HELI_LEANY]    ={9,10},
  278.     [WAC_HELI_LEANR]    ={6,5},
  279.     [WAC_HELI_UPDOWN]   ={3,4},
  280.     [WAC_HELI_START]    ={2,0},
  281.     [WAC_HELI_FIRE]     ={12,0},
  282.     [WAC_HELI_CAM]      ={11,0},
  283.     [WAC_HELI_NEXTWEP]  ={13,0},
  284.     [WAC_HELI_HOVER]    ={14,0},
  285.     [WAC_HELI_EXIT]     ={1,0},
  286. }
  287.  
  288. function ENT:Think()
  289.     local crt = CurTime()
  290.     if !self.Lock then
  291.         if self.UpdateSecond<crt then
  292.             if self.Phys and self.Phys:IsValid() then
  293.                 self.Phys:Wake()
  294.             end
  295.             if self.Burning then
  296.                 self:DamageEngine(0.1)
  297.             end
  298.             if self.CrRotorWash then
  299.                 if self.startMul > 0.6 then
  300.                     if !self.RotorWash then
  301.                         self.RotorWash = ents.Create("env_rotorwash_emitter")
  302.                         self.RotorWash:SetPos(self.Entity:GetPos())
  303.                         self.RotorWash:SetParent(self.Entity)
  304.                         self.RotorWash:Activate()
  305.                     end
  306.                 else
  307.                     if self.RotorWash then
  308.                         self.RotorWash:Remove()
  309.                         self.RotorWash = nil
  310.                     end
  311.                 end
  312.             end
  313.             if self.startMul > 0.1 then
  314.                 for k, v in pairs(ents.FindInSphere(self.Entity:GetPos(), 2000)) do
  315.                     if string.find(v:GetClass(), "rpg_missile") or string.find(v:GetClass(), "wac_w_rocket") then
  316.                         if !self.Sounds.MissileAlert[2] then
  317.                             self.Sounds.MissileAlert[2]=0
  318.                             self.Sounds.MissileAlert[1]:Play()
  319.                         end
  320.                         break
  321.                     elseif self.Sounds.MissileAlert[2] then
  322.                         self.Sounds.MissileAlert[2] = false
  323.                         self.Sounds.MissileAlert[1]:Stop()
  324.                     end
  325.                 end
  326.             end
  327.             if self.Smoke then
  328.                 self.Smoke:SetKeyValue("renderamt", tostring(math.Clamp(self.startMul*170, 0, 200)))
  329.                 self.Smoke:SetKeyValue("Speed", tostring(50+self.startMul*50))
  330.                 self.Smoke:SetKeyValue("JetLength", tostring(50+self.startMul*50))
  331.             end
  332.             self:UpdateSeats()
  333.             self.UpdateSecond = crt+0.1
  334.         end
  335.         if self:GetNWFloat("uptime") != math.Clamp(self.startMul,0,150) then
  336.             self:SetNWFloat("uptime", math.Clamp(self.startMul,0,150))
  337.         end
  338.         if self:GetNWFloat("up") != self.upMul then
  339.             self:SetNWFloat("up", self.upMul)
  340.         end
  341.         if self.TopRotor and self.TopRotor:WaterLevel() > 0 then
  342.             self:DamageEngine(0.5)
  343.         end
  344.         for k, t in pairs(self.SeatsT) do
  345.             local p=self.Passenger[k]
  346.             if p and p:IsValid() and p:InVehicle() and p:GetVehicle().BigOne then
  347.                 if k==1 then
  348.                     if self:GetPLControl(p,WAC_HELI_START,0,true)>0 and self.StartTime<CurTime() then
  349.                         self:SwitchState()
  350.                         self.StartTime=CurTime()+1
  351.                     end
  352.                     if self:GetPLControl(p,WAC_HELI_HOVER,0,true)>0 and self.HoverTime<CurTime() then
  353.                         self:ToggleHover()
  354.                         self.HoverTime=CurTime()+1
  355.                     end
  356.                 end
  357.                 if self:GetPLControl(p,WAC_HELI_CAM,0,true, self.SeatsT.Pilot!=k)>0 and (!p.NextCamSwitch or p.NextCamSwitch < crt) then
  358.                     p:SetNWBool("docam", !p:GetNWBool("docam"))
  359.                     p:SetNWBool("wac_mouse_seatinput", k==1 and p:GetNWBool("docam") or false)
  360.                     p.NextCamSwitch=crt+0.5
  361.                 end
  362.                 if t.wep then
  363.                     if self:GetPLControl(p,WAC_HELI_NEXTWEP,0,true, self.SeatsT.Pilot!=k)>0 and t.wep.NextSelect<CurTime() then
  364.                         self:NextWeapon(t.wep, k, p)
  365.                     end
  366.                     if self:GetPLControl(p,WAC_HELI_FIRE,0,true, self.SeatsT.Pilot!=k)>0 then
  367.                         t.wep[t.wep.act].func(self.Entity, t.wep[t.wep.act], p)
  368.                         self:SetNWFloat("seat_"..k.."_nextshot", t.wep[t.wep.act].NextShoot)
  369.                         self:SetNWFloat("seat_"..k.."_lastshot", t.wep[t.wep.act].LastShot)
  370.                         self:SetNWFloat("seat_"..k.."_ammo", t.wep[t.wep.act].Ammo)
  371.                     end
  372.                     if t.wep[t.wep.act].Think then t.wep[t.wep.act].Think(self.Entity, t.wep[t.wep.act], p) end
  373.                 end
  374.             end
  375.         end
  376.         for _, snd in pairs(self.Sounds) do
  377.             if snd[2] and snd[3] and snd[2] <= crt then
  378.                 snd[1]:Stop()
  379.                 if self:HasPassenger() or self.startMul > 0.01 then
  380.                     snd[1]:Play()
  381.                     snd[2] = crt+snd[3]
  382.                 end
  383.             end
  384.         end
  385.     end
  386.     self:NextThink(crt)
  387.     return true
  388. end
  389.  
  390. function ENT:SendKey(p,k,b)
  391.     if k==keyids[WAC_HELI_EXIT][1] then
  392.         self:EjectPassenger(p)
  393.         return
  394.     end
  395.     p.HeliKeysDown[k]=b
  396. end
  397.  
  398. function ENT:GetPLControl(pl, id, cur, static, nopilot)
  399.     local mul = tonumber(pl:GetInfo("wac_cl_heli_mul"))*WAC.Helicopter.CVars.PHM:GetFloat()
  400.     local tempJoyVal=0
  401.     if !nopilot and tonumber(pl:GetInfo("wac_cl_heli_usejoystick"))>0 and joystick then
  402.         tempJoyVal=joystick.Get(pl, "wac_heli_"..id)
  403.         tempJoyVal=(type(tempJoyVal)=="number")and(tempJoyVal)or((tempJoyVal==true)and(1)or(0))
  404.         local addiv=tempJoyVal/127.5-1
  405.         if static then return addiv end
  406.         return math.Clamp(math.pow(addiv, 3)*mul, -1, 1)
  407.     else
  408.         local swap=pl:GetInfo("wac_cl_heli_mouse_swap")
  409.         if (id==WAC_HELI_LEANP or (swap=="1"and id==WAC_HELI_LEANR) or (swap=="0" and id==WAC_HELI_LEANY)) and tonumber(pl:GetInfo("wac_cl_heli_mouse"))==1 then
  410.             local ang1=pl:GetAimVector():Angle()
  411.             local ang2=self:GetAngles()
  412.             if id==WAC_HELI_LEANP then
  413.                 local m=(pl:GetInfo("wac_cl_heli_mouse_invert_pitch")=="1" and -1 or 1)
  414.                 return math.Clamp(math.AngleDifference(ang1.p,ang2.p)/10*mul*m,-1,1)
  415.             else
  416.                 if swap=="1" then mul=mul*-1 end
  417.                 local m=(pl:GetInfo("wac_cl_heli_mouse_invert_yawroll")=="1" and -1 or 1)
  418.                 return math.Clamp(math.AngleDifference(ang1.y,ang2.y)/10*mul*m,-1,1)
  419.             end
  420.         else
  421.             if pl.HeliKeysDown and pl.HeliKeysDown[keyids[id][1]] then
  422.                 return math.Clamp(cur+0.03*mul, -1, 1)
  423.             elseif pl.HeliKeysDown and pl.HeliKeysDown[keyids[id][2]] then
  424.                 return math.Clamp(cur-0.03*mul, -1, 1)
  425.             end
  426.             if static then
  427.                 return cur - cur/7
  428.             end
  429.         end
  430.     end
  431.     return 0
  432. end
  433.  
  434. function ENT:HasPassenger()
  435.     for k, p in pairs(self.Passenger) do
  436.         if p and p:IsValid() then
  437.             return true
  438.         end
  439.     end
  440. end
  441.  
  442. function ENT:SetOn(b)
  443.     if b then
  444.         if self.Active then return end
  445.         self.Active = true
  446.     elseif self.Active then
  447.         self.Active=false
  448.     end
  449.     self:SetNWBool("active", self.Active)
  450. end
  451.  
  452. function ENT:SwitchState()
  453.     self:SetOn(!self.Active)
  454. end
  455.  
  456. function ENT:ToggleHover()
  457.     self.DoHover=!self.DoHover
  458.     self:SetNWBool("hover",self.DoHover)
  459. end
  460.  
  461. function ENT:PhysicsUpdate(ph)
  462.     if self.LastPhys==CurTime() then return end
  463.     local vel = ph:GetVelocity()   
  464.     local pos=self:GetPos()
  465.     local ri=self:GetRight()
  466.     local up=self:GetUp()
  467.     local fwd=self:GetForward()
  468.     local ang=self:GetAngles()
  469.     if !self.Lock then
  470.         local phm=WAC.Helicopter.CVars.PHM:GetFloat()
  471.         if self.UsePhysRotor then--########### With phys rotor
  472.             if self.TopRotor and self.TopRotor.Phys and self.TopRotor.Phys:IsValid() then
  473.                 local downvel = self.TopRotor:WorldToLocal(self.TopRotor:GetVelocity()+self.TopRotor:GetPos()).z
  474.                 local wingsubstr = (self.upMul/3 + (math.abs(self.pitchMul)+math.abs(self.yawMul)+math.abs(self.rollMul))*0.01 - math.Clamp(downvel*(self.upMul+1)*self.startMul/900, -0.1, 0.5))
  475.                 self.TopRotor.Phys:AddAngleVelocity(Vector(0,0,-wingsubstr)*self.TopRotorDir)
  476.                 self.startMul = math.Clamp(self.TopRotor.Phys:GetAngleVelocity().z/2500*self.TopRotorDir*phm,-1,1)
  477.                 if self.Active and self.TopRotor:WaterLevel() <= 0 then
  478.                     self.engineStart = math.Clamp(self.engineStart+FrameTime()*0.1*WAC.Helicopter.CVars.SSpeed:GetFloat(), 0, (self.engineHealth/160+self.TopRotor.fHealth/250)*0.2+0.8)
  479.                     self.TopRotor.Phys:AddAngleVelocity(Vector(0,0,self.engineStart*12+1+self.upMul*self.startMul)*self.TopRotorDir)
  480.                 else
  481.                     self.engineStart = math.Clamp(self.engineStart-FrameTime()*0.5*WAC.Helicopter.CVars.SSpeed:GetFloat(), 0, 1)
  482.                 end
  483.                 local tr = util.QuickTrace(self.TopRotor:LocalToWorld(Vector(0,0,self.TopRotor:OBBMaxs().z)), self.RotorWidth*self.TopRotor:GetRight()*math.cos(CurTime()*5)+self.TopRotor:GetForward()*math.sin(CurTime()*5), {self.Entity,self.TopRotor,self.BackRotor})
  484.                 if tr.Hit then
  485.                     if math.abs(self.startMul) > 0.1 then
  486.                         self:DamageBigRotor(math.abs(self.startMul*10))
  487.                         tr.Entity:TakeDamage(math.abs(self.startMul*30), self.Entity, self.Entity)
  488.                         return
  489.                     end
  490.                 end
  491.                 --[[local tr = util.QuickTrace(self:GetPos(), up*-300, self.Entity)
  492.                 if tr.Hit then
  493.                     self.addPressure = 300-tr.HitPos:Distance(tr.StartPos)
  494.                 else
  495.                     self.addPressure = 0
  496.                 end]]
  497.                 self.addPressure=0
  498.                 local mind = (100-self.TopRotor.fHealth)/100
  499.                 ph:AddAngleVelocity(Vector(math.Rand(-mind, mind)*self.startMul,math.Rand(-mind, mind)*self.startMul,math.Rand(-mind, mind)*self.startMul)*phm)
  500.                 if self.BackRotor and self.BackRotor:IsValid() and self.BackRotor.Phys:IsValid() then
  501.                     self.BackRotor.Phys:AddAngleVelocity(Vector(0,math.pow(self.startMul*20,2)*self.BackRotorDir,0))
  502.                     --[[if math.abs(self.BackRotor.Phys:GetAngleVelocity().y)<600 then
  503.                         ph:AddAngleVelocity(Vector(0,0,0-self.startMul*self.TopRotorDir)+ph:GetAngleVelocity()*0.01)
  504.                     end]]
  505.                 else
  506.                     ph:AddAngleVelocity(Vector(0,0,0-self.startMul*self.TopRotorDir)+ph:GetAngleVelocity()*0.01*phm)
  507.                     ph:AddAngleVelocity(Vector(math.Rand(-mind, mind)*self.startMul,math.Rand(-mind, mind)*self.startMul,math.Rand(-mind, mind)*self.startMul)*phm)
  508.                     if !self.Sounds.CrashAlarm[2] then
  509.                         self.Sounds.CrashAlarm[2] = 0
  510.                     end
  511.                 end
  512.                 local lvel=self:WorldToLocal(pos+vel)
  513.                 local dvel=vel:Length()
  514.                 ph:SetVelocity(vel+up*(self.upMul*self.startMul*1.7*self.EngineForce/20-(lvel*0.000001*self.startMul*dvel).z-(lvel*0.000001*self.startMul*dvel).y+self.startMul*9+math.pow(self.addPressure/500, 3)*(self.upMul+1.1))*phm)
  515.                 --ph:SetVelocity(vel*math.Clamp(vel:Length()/100,0.994,1)+self.dirs.up*(self.upMul*self.startMul*1.6-(self:WorldToLocal(self:GetPos()+vel)*0.001*self.startMul).z+self.startMul*8.6+math.pow(self.addPressure/500, 3)*(self.upMul+1.1))+(self.dirs.fwd*math.Clamp(self.dirs.ang.p*0.1, -2, 2)+self.dirs.ri*math.Clamp(self.dirs.ang.r*0.1, -2, 2))*self.startMul)
  516.                 --ph:SetVelocity(vel*math.Clamp(vel:Length()/100,0.994,1)+self:LocalToWorld(Vector(math.Clamp(ang.p*0.1, -2, 2)*self.startMul,math.Clamp(ang.y*0.1, -2, 2)*self.startMul,self.upMul*self.startMul*1.5+self.startMul*8.6+math.pow(self.addPressure/400, 3)*(self.upMul+1)))-self:GetPos())
  517.             elseif self.BackRotor and self.BackRotor:IsValid() and self.BackRotor.Phys:IsValid() then
  518.                 ph:AddAngleVelocity((ph:GetAngleVelocity()*0.01+Vector(0,0,self.BackRotor.Phys:GetAngleVelocity().y/300))*self.startMul)
  519.             end
  520.         else --########### Without phys rotor  
  521.             self.startMul=math.Approach(self.startMul, self.Active and 1 or 0, self.EngineForce/1000)
  522.             ph:SetVelocity(vel*0.999+(up*self.startMul*(self.upMul+1)*7 + (fwd*math.Clamp(ang.p*0.1, -2, 2) + ri*math.Clamp(ang.r*0.1, -2, 2))*self.startMul)*phm)
  523.         end
  524.  
  525.         if self.Passenger[1] and self.Passenger[1]:IsValid() and self.Passenger[1]:IsPlayer() then         
  526.             self.yawMul = self:GetPLControl(self.Passenger[1], WAC_HELI_LEANP, self.yawMul)
  527.             self.rollMul    = self.BackRotor and self:GetPLControl(self.Passenger[1], WAC_HELI_LEANY, self.rollMul) or 0
  528.             self.pitchMul   = self:GetPLControl(self.Passenger[1], WAC_HELI_LEANR, self.pitchMul)
  529.             self.upMul  = self:GetPLControl(self.Passenger[1], WAC_HELI_UPDOWN, self.upMul, true)          
  530.         end
  531.         local brakemul = 1
  532.         if self.Passenger[1] and self.Passenger[1]:IsValid() then
  533.             brakemul = tonumber(self.Passenger[1]:GetInfo("wac_cl_heli_easy")) 
  534.         end
  535.         local angbrake=((self.TopRotor and self.BackRotor) and ph:GetAngleVelocity()*self.AngBrakeMul*brakemul or NULLVEC)
  536.         local t=self:CalculateHover(ph,pos,vel,ang)
  537.         ph:AddAngleVelocity((Vector((self.pitchMul+t.r)*self.startMul, (self.yawMul+t.p)*self.startMul, self.rollMul*self.startMul)*brakemul-angbrake)*phm)
  538.     end
  539.     vel=ph:GetVelocity()
  540.     local tr=util.QuickTrace(self:GetPos(),vel:Normalize()*self:BoundingRadius(),self.Entity)
  541.     self.LastPhys=CurTime()
  542. end
  543.  
  544. function ENT:CalculateHover(ph,pos,vel,ang)
  545.     if self.DoHover then
  546.         local v=self:WorldToLocal(pos+vel)
  547.         local av=ph:GetAngleVelocity()
  548.         t={
  549.             p=math.Clamp(-ang.p*0.6-av.y*0.6-v.x*0.025,-0.65,0.65),
  550.             r=math.Clamp(-ang.r*0.6-av.x*0.6+v.y*0.025,-0.65,0.65)
  551.         }
  552.         return t
  553.     else
  554.         return {p=0,r=0}
  555.     end
  556. end
  557.  
  558. --[###########]
  559. --[###] DAMAGE
  560. --[###########]
  561.  
  562. function ENT:PhysicsCollide(cdat, phys)
  563.     if cdat.DeltaTime > 0.5 then
  564.         local mass = cdat.HitObject:GetMass()
  565.         if cdat.HitEntity:GetClass() == "worldspawn" then
  566.             mass = 1000
  567.         end
  568.         local dmg = (cdat.Speed*cdat.Speed*math.Clamp(mass, 0, 1000))/8000000
  569.         self:TakeDamage(dmg*10)
  570.         if dmg > 2 then
  571.             self.Entity:EmitSound("vehicles/v8/vehicle_impact_heavy"..math.random(1,4)..".wav")
  572.             local lasta=(self.LastDamageTaken<CurTime()+6 and self.LastAttacker or self.Entity)
  573.             for k, p in pairs(self.Passenger) do
  574.                 if p and p:IsValid() then
  575.                     p:TakeDamage(dmg/5, lasta, self.Entity)
  576.                 end
  577.             end
  578.         end
  579.     end
  580. end
  581.  
  582. function ENT:DamageSmallRotor(amt)
  583.     if amt < 1 then return end
  584.     self.Entity:EmitSound("physics/metal/metal_box_impact_bullet"..math.random(1,3)..".wav", math.Clamp(amt*40,0,200))
  585.     if self.BackRotor and self.BackRotor:IsValid() then
  586.         self.BackRotor.fHealth = self.BackRotor.fHealth - amt
  587.         self.BackRotor.Phys:AddAngleVelocity(Vector(0,-amt*40,0))
  588.         if self.BackRotor.fHealth < 0 then
  589.             self:KillBackRotor()
  590.             if !self.Sounds.CrashAlarm[2] then
  591.                 self.Sounds.CrashAlarm[2] = 0
  592.             end
  593.         elseif self.BackRotor.fHealth < 50 and !self.Sounds.MinorAlarm[2] then
  594.             self.Sounds.MinorAlarm[2] = 0
  595.         end
  596.         if self.BackRotor then
  597.             self:SetNWFloat("rotorhealth", self.BackRotor.fHealth)
  598.         else
  599.             self:SetNWFloat("rotorhealth", -1)
  600.         end
  601.         self:DamageEngine(amt/2)
  602.     end
  603. end
  604.  
  605. function ENT:KillBackRotor()
  606.     if !self.BackRotor then return end
  607.     local e = ents.Create("prop_physics")
  608.     e:SetAngles(self.BackRotor:GetAngles())
  609.     e:SetPos(self.BackRotor:GetPos())
  610.     e:SetModel(self.BackRotor:GetModel())
  611.     e:Spawn()
  612.     e:SetVelocity(self.BackRotor:GetUp()*300)
  613.     e:GetPhysicsObject():AddAngleVelocity(self:GetPhysicsObject():GetAngleVelocity())
  614.     self.BackRotor:Remove()
  615.     self.BackRotor=nil
  616.     timer.Simple(10, function()
  617.         if e and e:IsValid() then
  618.             e:Remove()
  619.         end
  620.     end)
  621. end
  622.  
  623. function ENT:DamageBigRotor(amt)
  624.     if amt < 1 then return end
  625.     self.Entity:EmitSound("physics/metal/metal_box_impact_bullet"..math.random(1,3)..".wav", math.Clamp(amt*40,0,300))
  626.     if self.TopRotor and self.TopRotor:IsValid() then
  627.         self.TopRotor.fHealth = self.TopRotor.fHealth - amt
  628.         self.TopRotor.Phys:AddAngleVelocity(Vector(0,0,-amt*40*self.TopRotorDir))
  629.         if self.TopRotor.fHealth < 0 then
  630.             self:KillTopRotor()
  631.             if !self.Sounds.CrashAlarm[2] then
  632.                 self.Sounds.CrashAlarm[2] = 0
  633.             end
  634.         elseif self.TopRotor.fHealth < 50 and !self.Sounds.MinorAlarm[2] then
  635.             self.Sounds.MinorAlarm[2] = 0
  636.         end
  637.         if amt>5 then
  638.             self:SetOn(false)
  639.         end
  640.         if self.TopRotor then
  641.             self:SetNWFloat("rotorhealth", self.TopRotor.fHealth)
  642.         else
  643.             self:SetNWFloat("rotorhealth", -1)
  644.         end
  645.         self:DamageEngine(amt/2)
  646.     end
  647. end
  648.  
  649. function ENT:KillTopRotor()
  650.     if !self.TopRotor then return end
  651.     local e = ents.Create("prop_physics")
  652.     e:SetModel(self.RotorModel)
  653.     e:SetPos(self.TopRotor:GetPos())
  654.     e:SetAngles(self.TopRotor:GetAngles())
  655.     e:Spawn()
  656.     e.Phys = e:GetPhysicsObject()
  657.     e.wac_ignore=true
  658.     if e.Phys and e.Phys:IsValid() then
  659.         e.Phys:SetMass(100)
  660.         e.Phys:AddAngleVelocity(self.TopRotor.Phys:GetAngleVelocity())
  661.         e.Phys:SetVelocity(self.TopRotor.Phys:GetAngleVelocity():Length()*self.TopRotor:GetUp()*0.5 + self.TopRotor:GetVelocity())
  662.     end
  663.     self.TopRotor:Remove()
  664.     self.TopRotor = nil
  665.     e:SetNotSolid(true)
  666.     timer.Simple(15, function()
  667.         if !e or !e:IsValid() then return end
  668.         e:Remove()
  669.     end)
  670. end
  671. --[###] Rotor Damage
  672.  
  673.  
  674. function ENT:OnTakeDamage(dmg)
  675.     if !dmg:IsExplosionDamage() then
  676.         dmg:ScaleDamage(0.25)
  677.     end
  678.     local rdmg = dmg:GetDamage()
  679.     self:DamageEngine(rdmg/5)
  680.     local pos=self:WorldToLocal(dmg:GetDamagePosition())
  681.     if pos.z>20 and pos.z<60 then
  682.         self:DamageBigRotor(rdmg/15)   
  683.     end
  684.     if pos.x<-150 and pos.x>-250 then
  685.         self:DamageSmallRotor(rdmg/2)
  686.     end
  687.     self.LastAttacker=dmg:GetAttacker()
  688.     self.LastDamageTaken=CurTime()
  689.     self:TakePhysicsDamage(dmg)
  690. end
  691.  
  692. function ENT:DamageEngine(amt)
  693.     self.engineHealth = self.engineHealth - amt
  694.     if self.engineHealth < 50  then
  695.         if !self.Sounds.MinorAlarm[2] then
  696.             self.Sounds.MinorAlarm[2] = 0
  697.         end
  698.         if !self.Smoke then
  699.             self.Smoke = self:CreateSmoke()
  700.         end
  701.         if self.engineHealth < 20 then
  702.             if !self.Sounds.LowHealth[2] then
  703.                 local fire = ents.Create("env_fire_trail")
  704.                 fire:SetPos(self:LocalToWorld(self.FirePos))
  705.                 fire:Spawn()
  706.                 fire:SetParent(self.Entity)
  707.                 self.Burning = true
  708.                 self.Sounds.LowHealth[2] = 0
  709.             end
  710.             if self.engineHealth < 0 and !self.Lock then
  711.                 self.Lock = true
  712.                 self:KillTopRotor()
  713.                 local lasta=(self.LastDamageTaken<CurTime()+6 and self.LastAttacker or self.Entity)
  714.                 for k, p in pairs(self.Passenger) do
  715.                     if p and p:IsValid() then
  716.                         p:TakeDamage(p:Health() + 20, lasta, self.Entity)
  717.                     end
  718.                 end
  719.                 for k,v in pairs(self.Seats) do
  720.                     v:Remove()
  721.                 end
  722.                 self.Passenger={}
  723.                 self:StopAllSounds()
  724.                 self.IgnoreDamage = false
  725.                 local effectdata = EffectData()
  726.                 effectdata:SetStart( self.Entity:GetPos())
  727.                 effectdata:SetOrigin( self.Entity:GetPos())
  728.                 effectdata:SetScale( 1 )
  729.                 util.Effect("Explosion", effectdata)
  730.                 util.Effect("HelicopterMegaBomb", effectdata)
  731.                 util.Effect("cball_explode", effectdata)
  732.                 util.BlastDamage(self.Entity, self.Entity, self.Entity:GetPos(), 300, 300)
  733.                 self:SetOn(false)
  734.                 if self.Smoke then
  735.                     self.Smoke:Remove()
  736.                     self.Smoke=nil
  737.                 end
  738.                 if self.RotorWash then
  739.                     self.RotorWash:Remove()
  740.                     self.RotorWash=nil
  741.                 end
  742.                 self:SetNWBool("locked", true)
  743.             end
  744.         end
  745.     end
  746.     if self.Smoke then
  747.         local rcol = math.Clamp(self.engineHealth*3.4, 0, 170)
  748.         self.Smoke:SetKeyValue("rendercolor", rcol.." "..rcol.." "..rcol)
  749.     end
  750.     self:SetNWFloat("health", self.engineHealth)
  751. end
  752.  
  753. function ENT:CreateSmoke()
  754.     local smoke = ents.Create("env_smokestack")
  755.     smoke:SetPos(self:LocalToWorld(self.SmokePos))
  756.     smoke:SetAngles(self:GetAngles()+Angle(-90,0,0))
  757.     smoke:SetKeyValue("InitialState", "1")
  758.     smoke:SetKeyValue("WindAngle", "0 0 0")
  759.     smoke:SetKeyValue("WindSpeed", "0")
  760.     smoke:SetKeyValue("rendercolor", "170 170 170")
  761.     smoke:SetKeyValue("renderamt", "170")
  762.     smoke:SetKeyValue("SmokeMaterial", "particle/smokesprites_0001.vmt")
  763.     smoke:SetKeyValue("BaseSpread", "2")
  764.     smoke:SetKeyValue("SpreadSpeed", "2")
  765.     smoke:SetKeyValue("Speed", "50")
  766.     smoke:SetKeyValue("StartSize", "10")
  767.     smoke:SetKeyValue("EndSize", "50")
  768.     smoke:SetKeyValue("roll", "10")
  769.     smoke:SetKeyValue("Rate", "15")
  770.     smoke:SetKeyValue("JetLength", "50")
  771.     smoke:SetKeyValue("twist", "5")
  772.     smoke:Spawn()
  773.     smoke:SetParent(self.Entity)
  774.     smoke:Activate()
  775.     return smoke
  776. end
  777.  
  778. function ENT:OnRemove()
  779.     for _,p in pairs(self.Passenger) do
  780.         if ValidEntity(p) then
  781.             p:SetNWInt("wac_passenger_id",0)
  782.             p.wac_passenger_id=0
  783.         end
  784.     end
  785.     if self.TopRotor and self.TopRotor:IsValid() then
  786.         self.TopRotor:Remove()
  787.     end
  788.     if self.BackRotor and self.BackRotor:IsValid() then
  789.         self.BackRotor:Remove()
  790.     end
  791.     for _,s in pairs(self.Sounds) do
  792.         s[1]:Stop()
  793.     end
  794. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement