Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- include("shared.lua")
- include("entities/base_wire_entity/init.lua")
- AddCSLuaFile("cl_init.lua")
- AddCSLuaFile("shared.lua")
- local NULLVEC=Vector(0,0,0)
- WAC.Helicopter.CVars={
- RPM=CreateConVar("wac_heli_rpmneeded", 2500, {FCVAR_REPLICATED, FCVAR_ARCHIVE}),
- SSpeed=CreateConVar("wac_heli_startspeed", 1, {FCVAR_REPLICATED, FCVAR_ARCHIVE}),
- PHM=CreateConVar("wac_heli_phmul", 1, {FCVAR_REPLICATED, FCVAR_ARCHIVE}),
- }
- WAC.Hook("SetPlayerAnimation", "SetHeliChairAnim", function(pl, anim)
- if pl:InVehicle() then
- local Veh = pl:GetVehicle()
- if string.find(Veh:GetModel(), "models/nova/airboat_seat") then
- local seq = pl:LookupSequence("sit")
- pl:SetPlaybackRate(1.0)
- pl:ResetSequence(seq)
- pl:SetCycle(0)
- return true
- end
- end
- end)
- function ENT:UpdateTransmitState() return TRANSMIT_ALWAYS end
- ENT.IgnoreDamage = true
- ENT.wac_ignore = true
- ENT.Model = nil
- ENT.RotorPhModel = nil
- ENT.RotorModel = nil
- ENT.BackRotorModel= nil
- ENT.UsePhysRotor = false
- ENT.Submersible = false
- ENT.CrRotorWash = false
- ENT.RotorWidth = 200
- ENT.TopRotorDir = -1
- ENT.BackRotorDir = -1
- ENT.TopRotorPos = Vector(0,0,50)
- ENT.BackRotorPos = Vector(-185,-3,13)
- ENT.EngineForce = 20
- ENT.BrakeMul = 1
- ENT.AngBrakeMul = 0.01
- ENT.Weight = 1000
- ENT.SeatSwitcherPos= Vector(0,0,50)
- ENT.MaxEnterDistance= 50
- function ENT:Initialize()
- self.Entity:SetModel(self.Model)
- self.Entity:PhysicsInit(SOLID_VPHYSICS)
- self.Entity:SetMoveType(MOVETYPE_VPHYSICS)
- self.Entity:SetSolid(SOLID_VPHYSICS)
- self.Phys = self.Entity:GetPhysicsObject()
- if self.Phys:IsValid() then
- self.Phys:SetMass(self.Weight)
- self.Phys:Wake()
- end
- self:AddRotor()
- self:AddSeats()
- self:AddSounds()
- self:AddWireInputs()
- self.UpdateSecond = 0
- self.wac_seatswitch = true
- self.StartTime = 0
- self.HoverTime=0
- self.engineHealth = 100
- self.pitchMul = 0
- self.yawMul = 0
- self.rollMul = 0
- self.startMul = 0
- self.upMul = 0
- self:SetNWFloat("health", 100)
- self.LastActivated = 0
- self.NextWepSwitch = 0
- self.NextCamSwitch = 0
- self.engineStart = 0
- self.LastPhys=0
- self.Passenger={}
- end
- function ENT:AddWireInputs()
- Wire_CreateInputs(self,{"Pitch","Yaw","Roll","Start","Thrust","Fire","NextWeapon"})
- end
- function ENT:TriggerInput(n,v)
- if n=="Pitch" then
- --self.yawMul
- end
- end
- function ENT:AddRotor()
- if self.UsePhysRotor then
- self.TopRotor = ents.Create("prop_physics")
- self.TopRotor:SetModel("models/props_junk/sawblade001a.mdl")
- self.TopRotor:SetPos(self:LocalToWorld(self.TopRotorPos))
- self.TopRotor:SetOwner(self.Owner)
- self.TopRotor:Spawn()
- self.TopRotor:SetNotSolid(true)
- self.TopRotor.Phys = self.TopRotor:GetPhysicsObject()
- self.TopRotor.Phys:EnableGravity(false)
- self.TopRotor.Phys:SetMass(5)
- self.TopRotor:SetColor(Color(0,0,0,0))
- self.TopRotor.fHealth = 100
- self.TopRotor.wac_ignore = true
- if self.RotorModel then
- local e = ents.Create("prop_physics")
- e:SetModel(self.RotorModel)
- e:SetPos(self:LocalToWorld(self.TopRotorPos))
- e:Spawn()
- e:SetOwner(self.Owner)
- e:SetNotSolid(true)
- e:SetParent(self.TopRotor)
- e.wac_ignore = true
- end
- self.BackRotor=self:AddBackRotor()
- self:SetNWEntity("rotor_rear",self.BackRotor)
- constraint.Axis(self.Entity, self.TopRotor, 0, 0, self.TopRotorPos, Vector(0,0,1),0,0,0.04,1)
- constraint.Axis(self.Entity, self.BackRotor, 0, 0, self.BackRotorPos, Vector(0,1,0) ,0,0,0.5,1)
- end
- end
- function ENT:AddBackRotor()
- local e=ents.Create("prop_physics")
- e:SetPos(self:LocalToWorld(self.BackRotorPos))
- e:SetModel(self.BackRotorModel)
- e:Spawn()
- e:SetOwner(self.Owner)
- e:SetNWFloat("rotorhealth", 100)
- e.wac_ignore=true
- e.Phys=e:GetPhysicsObject()
- if e.Phys:IsValid() then
- e.Phys:Wake()
- e.Phys:EnableGravity(false)
- e.Phys:EnableDrag(false)
- e.Phys:SetMass(10)
- end
- e.fHealth = 40
- return e
- end
- function ENT:AddSeats()
- self.Seats={}
- local ang=self:GetAngles()
- local e=ents.Create("wac_v_connector")
- e:SetPos(self:LocalToWorld(self.SeatSwitcherPos))
- e:SetColor(0,0,0,0)
- e:Spawn()
- e.wac_ignore = true
- e:SetParent(self.Entity)
- self.SeatSwitcher=e
- for k,v in pairs(self.SeatsT) do
- if type(v)=="table" and v.Pos then
- for _,t in pairs(v.wep) do
- if type(t)=="table" then
- if t.Init then t.Init(self,t) end
- end
- end
- self:SetNWInt("seat_"..k.."_actwep", 1)
- self:SetNWInt("seat_"..k.."_ammo", v.wep[1].Ammo)
- self.Seats[k]=ents.Create("prop_vehicle_prisoner_pod")
- --self.Seats[k]:SetKeyValue("vehiclescript","scripts/vehicles/HeliSeat.txt")
- self.Seats[k]:SetModel("models/nova/airboat_seat.mdl")
- self.Seats[k]:SetPos(self:LocalToWorld(v.Pos))
- self.Seats[k]:SetAngles(ang+Angle(0,-90,0))
- self.Seats[k]:Spawn()
- self.Seats[k]:SetColor(0,0,0,0)
- self.Seats[k].BigOne = self.Entity
- self.Seats[k].Phys = self.Seats[k]:GetPhysicsObject()
- self.Seats[k].Phys:EnableGravity(true)
- self.Seats[k].Phys:SetMass(1)
- self.Seats[k]:SetNotSolid(true)
- self.Seats[k]:SetParent(self.Entity)
- self.Seats[k].wac_ignore = true
- self.Seats[k]:SetNWEntity("BigOne", self.Entity)
- self.SeatSwitcher:AddVehicle(self.Seats[k])
- end
- end
- end
- function ENT:NextWeapon(t,k,p)
- if t[t.act].DeSelect then t[t.act].DeSelect(self.Entity, t[t.act], p) end
- t.act=(t.act<#t)and(t.act+1)or(1)
- t.NextSelect=CurTime()+0.5
- self:SetNWInt("seat_"..k.."_actwep", t.act)
- self:SetNWFloat("seat_"..k.."_nextshot", t[t.act].NextShoot)
- self:SetNWFloat("seat_"..k.."_lastshot", t[t.act].LastShot)
- self:SetNWFloat("seat_"..k.."_ammo", t[t.act].Ammo)
- end
- function ENT:SeatSwitch(p, s)
- if !self.Seats[s] then return end
- local psngr = self.Seats[s]:GetPassenger()
- if !psngr or !psngr:IsValid() or !psngr:InVehicle() then
- p:ExitVehicle()
- p:EnterVehicle(self.Seats[s])
- self:UpdateSeats()
- end
- end
- function ENT:EjectPassenger(ply,idx,t)
- if ply.LastVehicleEntered and ply.LastVehicleEntered<CurTime() then
- if !idx then
- for k,p in pairs(self.Passenger) do
- if p==ply then idx=k end
- end
- if !idx then
- return
- end
- end
- ply.LastVehicleEntered = CurTime()+0.5
- ply:ExitVehicle()
- ply:SetPos(self:LocalToWorld(self.SeatsT[idx].ExitPos))
- ply:SetVelocity(self:GetPhysicsObject():GetVelocity()*0.8)
- self:UpdateSeats()
- end
- end
- function ENT:Use(act, cal)
- if self.Lock then return end
- local crt = CurTime()
- if !act.LastVehicleEntered or act.LastVehicleEntered < crt then
- local d=self.MaxEnterDistance
- local v
- for k,veh in pairs(self.Seats) do
- if veh and veh:IsValid() then
- local psngr = veh:GetPassenger()
- if !psngr or !psngr:IsValid() then
- local dist=veh:GetPos():Distance(util.QuickTrace(act:GetShootPos(),act:GetAimVector()*self.MaxEnterDistance,act).HitPos)
- if dist<d then
- d=dist
- v=veh
- end
- end
- end
- end
- if v then
- act.HeliKeysDown={}
- act:EnterVehicle(v)
- act.LastVehicleEntered=crt+0.5
- end
- end
- self:UpdateSeats()
- end
- function ENT:UpdateSeats()
- for k, veh in pairs(self.Seats) do
- if !veh:IsValid() then return end
- local p = veh:GetPassenger()
- if self.Passenger[k] != p then
- if ValidEntity(self.Passenger[k]) then
- self.Passenger[k].HeliKeysDown={}
- self.Passenger[k]:SetNWEntity("BigOne", NULL)
- --self.Passenger[k]:SetNWInt("wac_passenger_id",0)
- --self.Passenger[k].wac_passenger_id=0
- end
- self:SetNWEntity("passenger_"..k, p)
- p:SetNWInt("wac_passenger_id",k)
- p.wac_passenger_id=k
- self.Passenger[k]=p
- end
- end
- end
- function ENT:StopAllSounds()
- for k, s in pairs(self.Sounds) do
- s[2] = false
- s[1]:Stop()
- end
- end
- local keyids={
- [WAC_HELI_LEANP] ={7,8},
- [WAC_HELI_LEANY] ={9,10},
- [WAC_HELI_LEANR] ={6,5},
- [WAC_HELI_UPDOWN] ={3,4},
- [WAC_HELI_START] ={2,0},
- [WAC_HELI_FIRE] ={12,0},
- [WAC_HELI_CAM] ={11,0},
- [WAC_HELI_NEXTWEP] ={13,0},
- [WAC_HELI_HOVER] ={14,0},
- [WAC_HELI_EXIT] ={1,0},
- }
- function ENT:Think()
- local crt = CurTime()
- if !self.Lock then
- if self.UpdateSecond<crt then
- if self.Phys and self.Phys:IsValid() then
- self.Phys:Wake()
- end
- if self.Burning then
- self:DamageEngine(0.1)
- end
- if self.CrRotorWash then
- if self.startMul > 0.6 then
- if !self.RotorWash then
- self.RotorWash = ents.Create("env_rotorwash_emitter")
- self.RotorWash:SetPos(self.Entity:GetPos())
- self.RotorWash:SetParent(self.Entity)
- self.RotorWash:Activate()
- end
- else
- if self.RotorWash then
- self.RotorWash:Remove()
- self.RotorWash = nil
- end
- end
- end
- if self.startMul > 0.1 then
- for k, v in pairs(ents.FindInSphere(self.Entity:GetPos(), 2000)) do
- if string.find(v:GetClass(), "rpg_missile") or string.find(v:GetClass(), "wac_w_rocket") then
- if !self.Sounds.MissileAlert[2] then
- self.Sounds.MissileAlert[2]=0
- self.Sounds.MissileAlert[1]:Play()
- end
- break
- elseif self.Sounds.MissileAlert[2] then
- self.Sounds.MissileAlert[2] = false
- self.Sounds.MissileAlert[1]:Stop()
- end
- end
- end
- if self.Smoke then
- self.Smoke:SetKeyValue("renderamt", tostring(math.Clamp(self.startMul*170, 0, 200)))
- self.Smoke:SetKeyValue("Speed", tostring(50+self.startMul*50))
- self.Smoke:SetKeyValue("JetLength", tostring(50+self.startMul*50))
- end
- self:UpdateSeats()
- self.UpdateSecond = crt+0.1
- end
- if self:GetNWFloat("uptime") != math.Clamp(self.startMul,0,150) then
- self:SetNWFloat("uptime", math.Clamp(self.startMul,0,150))
- end
- if self:GetNWFloat("up") != self.upMul then
- self:SetNWFloat("up", self.upMul)
- end
- if self.TopRotor and self.TopRotor:WaterLevel() > 0 then
- self:DamageEngine(0.5)
- end
- for k, t in pairs(self.SeatsT) do
- local p=self.Passenger[k]
- if p and p:IsValid() and p:InVehicle() and p:GetVehicle().BigOne then
- if k==1 then
- if self:GetPLControl(p,WAC_HELI_START,0,true)>0 and self.StartTime<CurTime() then
- self:SwitchState()
- self.StartTime=CurTime()+1
- end
- if self:GetPLControl(p,WAC_HELI_HOVER,0,true)>0 and self.HoverTime<CurTime() then
- self:ToggleHover()
- self.HoverTime=CurTime()+1
- end
- end
- if self:GetPLControl(p,WAC_HELI_CAM,0,true, self.SeatsT.Pilot!=k)>0 and (!p.NextCamSwitch or p.NextCamSwitch < crt) then
- p:SetNWBool("docam", !p:GetNWBool("docam"))
- p:SetNWBool("wac_mouse_seatinput", k==1 and p:GetNWBool("docam") or false)
- p.NextCamSwitch=crt+0.5
- end
- if t.wep then
- if self:GetPLControl(p,WAC_HELI_NEXTWEP,0,true, self.SeatsT.Pilot!=k)>0 and t.wep.NextSelect<CurTime() then
- self:NextWeapon(t.wep, k, p)
- end
- if self:GetPLControl(p,WAC_HELI_FIRE,0,true, self.SeatsT.Pilot!=k)>0 then
- t.wep[t.wep.act].func(self.Entity, t.wep[t.wep.act], p)
- self:SetNWFloat("seat_"..k.."_nextshot", t.wep[t.wep.act].NextShoot)
- self:SetNWFloat("seat_"..k.."_lastshot", t.wep[t.wep.act].LastShot)
- self:SetNWFloat("seat_"..k.."_ammo", t.wep[t.wep.act].Ammo)
- end
- if t.wep[t.wep.act].Think then t.wep[t.wep.act].Think(self.Entity, t.wep[t.wep.act], p) end
- end
- end
- end
- for _, snd in pairs(self.Sounds) do
- if snd[2] and snd[3] and snd[2] <= crt then
- snd[1]:Stop()
- if self:HasPassenger() or self.startMul > 0.01 then
- snd[1]:Play()
- snd[2] = crt+snd[3]
- end
- end
- end
- end
- self:NextThink(crt)
- return true
- end
- function ENT:SendKey(p,k,b)
- if k==keyids[WAC_HELI_EXIT][1] then
- self:EjectPassenger(p)
- return
- end
- p.HeliKeysDown[k]=b
- end
- function ENT:GetPLControl(pl, id, cur, static, nopilot)
- local mul = tonumber(pl:GetInfo("wac_cl_heli_mul"))*WAC.Helicopter.CVars.PHM:GetFloat()
- local tempJoyVal=0
- if !nopilot and tonumber(pl:GetInfo("wac_cl_heli_usejoystick"))>0 and joystick then
- tempJoyVal=joystick.Get(pl, "wac_heli_"..id)
- tempJoyVal=(type(tempJoyVal)=="number")and(tempJoyVal)or((tempJoyVal==true)and(1)or(0))
- local addiv=tempJoyVal/127.5-1
- if static then return addiv end
- return math.Clamp(math.pow(addiv, 3)*mul, -1, 1)
- else
- local swap=pl:GetInfo("wac_cl_heli_mouse_swap")
- 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
- local ang1=pl:GetAimVector():Angle()
- local ang2=self:GetAngles()
- if id==WAC_HELI_LEANP then
- local m=(pl:GetInfo("wac_cl_heli_mouse_invert_pitch")=="1" and -1 or 1)
- return math.Clamp(math.AngleDifference(ang1.p,ang2.p)/10*mul*m,-1,1)
- else
- if swap=="1" then mul=mul*-1 end
- local m=(pl:GetInfo("wac_cl_heli_mouse_invert_yawroll")=="1" and -1 or 1)
- return math.Clamp(math.AngleDifference(ang1.y,ang2.y)/10*mul*m,-1,1)
- end
- else
- if pl.HeliKeysDown and pl.HeliKeysDown[keyids[id][1]] then
- return math.Clamp(cur+0.03*mul, -1, 1)
- elseif pl.HeliKeysDown and pl.HeliKeysDown[keyids[id][2]] then
- return math.Clamp(cur-0.03*mul, -1, 1)
- end
- if static then
- return cur - cur/7
- end
- end
- end
- return 0
- end
- function ENT:HasPassenger()
- for k, p in pairs(self.Passenger) do
- if p and p:IsValid() then
- return true
- end
- end
- end
- function ENT:SetOn(b)
- if b then
- if self.Active then return end
- self.Active = true
- elseif self.Active then
- self.Active=false
- end
- self:SetNWBool("active", self.Active)
- end
- function ENT:SwitchState()
- self:SetOn(!self.Active)
- end
- function ENT:ToggleHover()
- self.DoHover=!self.DoHover
- self:SetNWBool("hover",self.DoHover)
- end
- function ENT:PhysicsUpdate(ph)
- if self.LastPhys==CurTime() then return end
- local vel = ph:GetVelocity()
- local pos=self:GetPos()
- local ri=self:GetRight()
- local up=self:GetUp()
- local fwd=self:GetForward()
- local ang=self:GetAngles()
- if !self.Lock then
- local phm=WAC.Helicopter.CVars.PHM:GetFloat()
- if self.UsePhysRotor then--########### With phys rotor
- if self.TopRotor and self.TopRotor.Phys and self.TopRotor.Phys:IsValid() then
- local downvel = self.TopRotor:WorldToLocal(self.TopRotor:GetVelocity()+self.TopRotor:GetPos()).z
- 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))
- self.TopRotor.Phys:AddAngleVelocity(Vector(0,0,-wingsubstr)*self.TopRotorDir)
- self.startMul = math.Clamp(self.TopRotor.Phys:GetAngleVelocity().z/2500*self.TopRotorDir*phm,-1,1)
- if self.Active and self.TopRotor:WaterLevel() <= 0 then
- 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)
- self.TopRotor.Phys:AddAngleVelocity(Vector(0,0,self.engineStart*12+1+self.upMul*self.startMul)*self.TopRotorDir)
- else
- self.engineStart = math.Clamp(self.engineStart-FrameTime()*0.5*WAC.Helicopter.CVars.SSpeed:GetFloat(), 0, 1)
- end
- 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})
- if tr.Hit then
- if math.abs(self.startMul) > 0.1 then
- self:DamageBigRotor(math.abs(self.startMul*10))
- tr.Entity:TakeDamage(math.abs(self.startMul*30), self.Entity, self.Entity)
- return
- end
- end
- --[[local tr = util.QuickTrace(self:GetPos(), up*-300, self.Entity)
- if tr.Hit then
- self.addPressure = 300-tr.HitPos:Distance(tr.StartPos)
- else
- self.addPressure = 0
- end]]
- self.addPressure=0
- local mind = (100-self.TopRotor.fHealth)/100
- ph:AddAngleVelocity(Vector(math.Rand(-mind, mind)*self.startMul,math.Rand(-mind, mind)*self.startMul,math.Rand(-mind, mind)*self.startMul)*phm)
- if self.BackRotor and self.BackRotor:IsValid() and self.BackRotor.Phys:IsValid() then
- self.BackRotor.Phys:AddAngleVelocity(Vector(0,math.pow(self.startMul*20,2)*self.BackRotorDir,0))
- --[[if math.abs(self.BackRotor.Phys:GetAngleVelocity().y)<600 then
- ph:AddAngleVelocity(Vector(0,0,0-self.startMul*self.TopRotorDir)+ph:GetAngleVelocity()*0.01)
- end]]
- else
- ph:AddAngleVelocity(Vector(0,0,0-self.startMul*self.TopRotorDir)+ph:GetAngleVelocity()*0.01*phm)
- ph:AddAngleVelocity(Vector(math.Rand(-mind, mind)*self.startMul,math.Rand(-mind, mind)*self.startMul,math.Rand(-mind, mind)*self.startMul)*phm)
- if !self.Sounds.CrashAlarm[2] then
- self.Sounds.CrashAlarm[2] = 0
- end
- end
- local lvel=self:WorldToLocal(pos+vel)
- local dvel=vel:Length()
- 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)
- --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)
- --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())
- elseif self.BackRotor and self.BackRotor:IsValid() and self.BackRotor.Phys:IsValid() then
- ph:AddAngleVelocity((ph:GetAngleVelocity()*0.01+Vector(0,0,self.BackRotor.Phys:GetAngleVelocity().y/300))*self.startMul)
- end
- else --########### Without phys rotor
- self.startMul=math.Approach(self.startMul, self.Active and 1 or 0, self.EngineForce/1000)
- 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)
- end
- if self.Passenger[1] and self.Passenger[1]:IsValid() and self.Passenger[1]:IsPlayer() then
- self.yawMul = self:GetPLControl(self.Passenger[1], WAC_HELI_LEANP, self.yawMul)
- self.rollMul = self.BackRotor and self:GetPLControl(self.Passenger[1], WAC_HELI_LEANY, self.rollMul) or 0
- self.pitchMul = self:GetPLControl(self.Passenger[1], WAC_HELI_LEANR, self.pitchMul)
- self.upMul = self:GetPLControl(self.Passenger[1], WAC_HELI_UPDOWN, self.upMul, true)
- end
- local brakemul = 1
- if self.Passenger[1] and self.Passenger[1]:IsValid() then
- brakemul = tonumber(self.Passenger[1]:GetInfo("wac_cl_heli_easy"))
- end
- local angbrake=((self.TopRotor and self.BackRotor) and ph:GetAngleVelocity()*self.AngBrakeMul*brakemul or NULLVEC)
- local t=self:CalculateHover(ph,pos,vel,ang)
- ph:AddAngleVelocity((Vector((self.pitchMul+t.r)*self.startMul, (self.yawMul+t.p)*self.startMul, self.rollMul*self.startMul)*brakemul-angbrake)*phm)
- end
- vel=ph:GetVelocity()
- local tr=util.QuickTrace(self:GetPos(),vel:Normalize()*self:BoundingRadius(),self.Entity)
- self.LastPhys=CurTime()
- end
- function ENT:CalculateHover(ph,pos,vel,ang)
- if self.DoHover then
- local v=self:WorldToLocal(pos+vel)
- local av=ph:GetAngleVelocity()
- t={
- p=math.Clamp(-ang.p*0.6-av.y*0.6-v.x*0.025,-0.65,0.65),
- r=math.Clamp(-ang.r*0.6-av.x*0.6+v.y*0.025,-0.65,0.65)
- }
- return t
- else
- return {p=0,r=0}
- end
- end
- --[###########]
- --[###] DAMAGE
- --[###########]
- function ENT:PhysicsCollide(cdat, phys)
- if cdat.DeltaTime > 0.5 then
- local mass = cdat.HitObject:GetMass()
- if cdat.HitEntity:GetClass() == "worldspawn" then
- mass = 1000
- end
- local dmg = (cdat.Speed*cdat.Speed*math.Clamp(mass, 0, 1000))/8000000
- self:TakeDamage(dmg*10)
- if dmg > 2 then
- self.Entity:EmitSound("vehicles/v8/vehicle_impact_heavy"..math.random(1,4)..".wav")
- local lasta=(self.LastDamageTaken<CurTime()+6 and self.LastAttacker or self.Entity)
- for k, p in pairs(self.Passenger) do
- if p and p:IsValid() then
- p:TakeDamage(dmg/5, lasta, self.Entity)
- end
- end
- end
- end
- end
- function ENT:DamageSmallRotor(amt)
- if amt < 1 then return end
- self.Entity:EmitSound("physics/metal/metal_box_impact_bullet"..math.random(1,3)..".wav", math.Clamp(amt*40,0,200))
- if self.BackRotor and self.BackRotor:IsValid() then
- self.BackRotor.fHealth = self.BackRotor.fHealth - amt
- self.BackRotor.Phys:AddAngleVelocity(Vector(0,-amt*40,0))
- if self.BackRotor.fHealth < 0 then
- self:KillBackRotor()
- if !self.Sounds.CrashAlarm[2] then
- self.Sounds.CrashAlarm[2] = 0
- end
- elseif self.BackRotor.fHealth < 50 and !self.Sounds.MinorAlarm[2] then
- self.Sounds.MinorAlarm[2] = 0
- end
- if self.BackRotor then
- self:SetNWFloat("rotorhealth", self.BackRotor.fHealth)
- else
- self:SetNWFloat("rotorhealth", -1)
- end
- self:DamageEngine(amt/2)
- end
- end
- function ENT:KillBackRotor()
- if !self.BackRotor then return end
- local e = ents.Create("prop_physics")
- e:SetAngles(self.BackRotor:GetAngles())
- e:SetPos(self.BackRotor:GetPos())
- e:SetModel(self.BackRotor:GetModel())
- e:Spawn()
- e:SetVelocity(self.BackRotor:GetUp()*300)
- e:GetPhysicsObject():AddAngleVelocity(self:GetPhysicsObject():GetAngleVelocity())
- self.BackRotor:Remove()
- self.BackRotor=nil
- timer.Simple(10, function()
- if e and e:IsValid() then
- e:Remove()
- end
- end)
- end
- function ENT:DamageBigRotor(amt)
- if amt < 1 then return end
- self.Entity:EmitSound("physics/metal/metal_box_impact_bullet"..math.random(1,3)..".wav", math.Clamp(amt*40,0,300))
- if self.TopRotor and self.TopRotor:IsValid() then
- self.TopRotor.fHealth = self.TopRotor.fHealth - amt
- self.TopRotor.Phys:AddAngleVelocity(Vector(0,0,-amt*40*self.TopRotorDir))
- if self.TopRotor.fHealth < 0 then
- self:KillTopRotor()
- if !self.Sounds.CrashAlarm[2] then
- self.Sounds.CrashAlarm[2] = 0
- end
- elseif self.TopRotor.fHealth < 50 and !self.Sounds.MinorAlarm[2] then
- self.Sounds.MinorAlarm[2] = 0
- end
- if amt>5 then
- self:SetOn(false)
- end
- if self.TopRotor then
- self:SetNWFloat("rotorhealth", self.TopRotor.fHealth)
- else
- self:SetNWFloat("rotorhealth", -1)
- end
- self:DamageEngine(amt/2)
- end
- end
- function ENT:KillTopRotor()
- if !self.TopRotor then return end
- local e = ents.Create("prop_physics")
- e:SetModel(self.RotorModel)
- e:SetPos(self.TopRotor:GetPos())
- e:SetAngles(self.TopRotor:GetAngles())
- e:Spawn()
- e.Phys = e:GetPhysicsObject()
- e.wac_ignore=true
- if e.Phys and e.Phys:IsValid() then
- e.Phys:SetMass(100)
- e.Phys:AddAngleVelocity(self.TopRotor.Phys:GetAngleVelocity())
- e.Phys:SetVelocity(self.TopRotor.Phys:GetAngleVelocity():Length()*self.TopRotor:GetUp()*0.5 + self.TopRotor:GetVelocity())
- end
- self.TopRotor:Remove()
- self.TopRotor = nil
- e:SetNotSolid(true)
- timer.Simple(15, function()
- if !e or !e:IsValid() then return end
- e:Remove()
- end)
- end
- --[###] Rotor Damage
- function ENT:OnTakeDamage(dmg)
- if !dmg:IsExplosionDamage() then
- dmg:ScaleDamage(0.25)
- end
- local rdmg = dmg:GetDamage()
- self:DamageEngine(rdmg/5)
- local pos=self:WorldToLocal(dmg:GetDamagePosition())
- if pos.z>20 and pos.z<60 then
- self:DamageBigRotor(rdmg/15)
- end
- if pos.x<-150 and pos.x>-250 then
- self:DamageSmallRotor(rdmg/2)
- end
- self.LastAttacker=dmg:GetAttacker()
- self.LastDamageTaken=CurTime()
- self:TakePhysicsDamage(dmg)
- end
- function ENT:DamageEngine(amt)
- self.engineHealth = self.engineHealth - amt
- if self.engineHealth < 50 then
- if !self.Sounds.MinorAlarm[2] then
- self.Sounds.MinorAlarm[2] = 0
- end
- if !self.Smoke then
- self.Smoke = self:CreateSmoke()
- end
- if self.engineHealth < 20 then
- if !self.Sounds.LowHealth[2] then
- local fire = ents.Create("env_fire_trail")
- fire:SetPos(self:LocalToWorld(self.FirePos))
- fire:Spawn()
- fire:SetParent(self.Entity)
- self.Burning = true
- self.Sounds.LowHealth[2] = 0
- end
- if self.engineHealth < 0 and !self.Lock then
- self.Lock = true
- self:KillTopRotor()
- local lasta=(self.LastDamageTaken<CurTime()+6 and self.LastAttacker or self.Entity)
- for k, p in pairs(self.Passenger) do
- if p and p:IsValid() then
- p:TakeDamage(p:Health() + 20, lasta, self.Entity)
- end
- end
- for k,v in pairs(self.Seats) do
- v:Remove()
- end
- self.Passenger={}
- self:StopAllSounds()
- self.IgnoreDamage = false
- local effectdata = EffectData()
- effectdata:SetStart( self.Entity:GetPos())
- effectdata:SetOrigin( self.Entity:GetPos())
- effectdata:SetScale( 1 )
- util.Effect("Explosion", effectdata)
- util.Effect("HelicopterMegaBomb", effectdata)
- util.Effect("cball_explode", effectdata)
- util.BlastDamage(self.Entity, self.Entity, self.Entity:GetPos(), 300, 300)
- self:SetOn(false)
- if self.Smoke then
- self.Smoke:Remove()
- self.Smoke=nil
- end
- if self.RotorWash then
- self.RotorWash:Remove()
- self.RotorWash=nil
- end
- self:SetNWBool("locked", true)
- end
- end
- end
- if self.Smoke then
- local rcol = math.Clamp(self.engineHealth*3.4, 0, 170)
- self.Smoke:SetKeyValue("rendercolor", rcol.." "..rcol.." "..rcol)
- end
- self:SetNWFloat("health", self.engineHealth)
- end
- function ENT:CreateSmoke()
- local smoke = ents.Create("env_smokestack")
- smoke:SetPos(self:LocalToWorld(self.SmokePos))
- smoke:SetAngles(self:GetAngles()+Angle(-90,0,0))
- smoke:SetKeyValue("InitialState", "1")
- smoke:SetKeyValue("WindAngle", "0 0 0")
- smoke:SetKeyValue("WindSpeed", "0")
- smoke:SetKeyValue("rendercolor", "170 170 170")
- smoke:SetKeyValue("renderamt", "170")
- smoke:SetKeyValue("SmokeMaterial", "particle/smokesprites_0001.vmt")
- smoke:SetKeyValue("BaseSpread", "2")
- smoke:SetKeyValue("SpreadSpeed", "2")
- smoke:SetKeyValue("Speed", "50")
- smoke:SetKeyValue("StartSize", "10")
- smoke:SetKeyValue("EndSize", "50")
- smoke:SetKeyValue("roll", "10")
- smoke:SetKeyValue("Rate", "15")
- smoke:SetKeyValue("JetLength", "50")
- smoke:SetKeyValue("twist", "5")
- smoke:Spawn()
- smoke:SetParent(self.Entity)
- smoke:Activate()
- return smoke
- end
- function ENT:OnRemove()
- for _,p in pairs(self.Passenger) do
- if ValidEntity(p) then
- p:SetNWInt("wac_passenger_id",0)
- p.wac_passenger_id=0
- end
- end
- if self.TopRotor and self.TopRotor:IsValid() then
- self.TopRotor:Remove()
- end
- if self.BackRotor and self.BackRotor:IsValid() then
- self.BackRotor:Remove()
- end
- for _,s in pairs(self.Sounds) do
- s[1]:Stop()
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement