Skip to content

Instantly share code, notes, and snippets.

@CapsAdmin
Created March 25, 2018 03:12
Show Gist options
  • Save CapsAdmin/72aed67f9e416632a96c9b25da9c3f9d to your computer and use it in GitHub Desktop.
Save CapsAdmin/72aed67f9e416632a96c9b25da9c3f9d to your computer and use it in GitHub Desktop.
local DEBUG = GetConVarNumber("developer") > 0
local DEBUG2 = true
do
local MOVED = {}
local MOVE_REF = {}
local function net_write(ent, vec, ang)
net.WriteEntity(ent)
net.WriteInt(vec.x, 16)
net.WriteInt(vec.y, 16)
net.WriteInt(vec.z, 16)
net.WriteInt(ang.x, 9)
net.WriteInt(ang.y, 9)
net.WriteInt(ang.z, 9)
end
local function net_read()
local ent = net.ReadEntity()
if not ent:IsValid() then return end
local x = net.ReadInt(16)
local y = net.ReadInt(16)
local z = net.ReadInt(16)
local p = net.ReadInt(9)
local yaw = net.ReadInt(9)
local r = net.ReadInt(9)
return ent, Vector(x,y,z), Angle(p,yaw,r)
end
local function WRITE_COUNT(n)
net.WriteUInt(n, 16)
end
local function READ_COUNT()
return net.ReadUInt(16)
end
if SERVER then
--hook.Remove("Think", "seagull_update")
hook.Add("Think", "seagull_update", function()
local seagulls = ents.FindByClass("monster_seagull")
for _, self in ipairs(seagulls) do
--[[if not self.seagull_untransmit then
self.seagull_untransmit_timer = self.seagull_untransmit_timer or CurTime() + 1
if self.seagull_untransmit_timer < CurTime() then
for i,v in ipairs(player.GetAll()) do
self:SetPreventTransmit(v, true)
end
self.seagull_untransmit = true
end
end]]
if not self.notransmit then
function self:UpdateTransmitState()
return TRANSMIT_NEVER
end
self.notransmit = true
self.checktransmit = CurTime() + 1
end
if self.checktransmit < CurTime() then
self:AddEFlags( EFL_FORCE_CHECK_TRANSMIT )
end
local updatedPos = false
local curPos = self:GetPos() --curPos.x = math.Round(curPos.x) curPos.y = math.Round(curPos.y)
if self.LastStoredPos ~= curPos then
self.LastStoredPos = curPos
updatedPos = true
end
local curAng = self:GetAngles() --curAng.x = math.Round(curAng.x) curAng.y = math.Round(curAng.y) curAng.z = math.Round(curAng.z)
if self.LastStoredAng ~= curAng then
self.LastStoredAng = curAng
updatedPos = true
end
-- when the seagull is standing still emit the data once
local important = false
if self.VelocityLength and self.VelocityLength < 5 then
if not self.seagull_sent_important then
updatedPos = true
self.LastStoredPos = curPos
self.LastStoredAng = curAng
important = true
self.seagull_sent_important = true
end
else
self.seagull_sent_important = false
end
if updatedPos == true then
local tableId = #MOVED + 1
local data = MOVE_REF[self]
if data ~= nil then
data[2] = self:GetPos()
data[3] = self:GetAngles()
--print("Updating move record")
else
-- Insert new queue record, keep order.
table.insert(MOVED, {self, self:GetPos(), self:GetAngles(), tableId} )
MOVE_REF[self] = MOVED[tableId]
--print("Added move record")
end
else
--print("No update")
end
end
local available = math.min(table.Count(MOVED), 10)
if available == 0 then
return
end
if important then
net.Start("seagull_update", false)
else
net.Start("seagull_update", true)
end
WRITE_COUNT(available)
local centerPos = Vector(0, 0, 0)
for i = 1, available do
local data = MOVED[1]
net_write(data[1], data[2], data[3])
centerPos = centerPos + data[2]
MOVE_REF[data[1]] = nil
table.remove(MOVED, 1)
end
if important then
net.Broadcast()
else
net.SendPVS(centerPos / available)
end
end)
util.AddNetworkString("seagull_update")
end
if CLIENT then
net.Receive("seagull_update", function()
local count = READ_COUNT()
for i = 1, count do
local self, pos, ang = net_read()
if not self then return end
self.net_pos = pos
self.net_ang = ang
end
end)
end
end
local ENT = {}
ENT.ClassName = "monster_seagull"
ENT.Type = "anim"
ENT.Base = "base_anim"
ENT.Spawnable = true
ENT.AdminSpawnable = false
ENT.PrintName = "seagull mount"
ENT.Model = "models/seagull.mdl"
do
local util_TraceLine = util.TraceLine
local temp = {}
function ENT:RayCast(a, b, tries)
temp.start = a
temp.endpos = b
temp.output = temp
return util_TraceLine(temp)
end
end
function ENT:SetupDataTables()
self:NetworkVar("Float", 0, "Size")
end
function ENT:Initialize()
self:DrawShadow(false)
if CLIENT then
self.csmodel = ClientsideModel(ENT.Model)
self.csmodel:SetParent(self)
self.csmodel:SetLOD(0)
end
self:SetSize(math.Rand(15, 25))
self:Think()
self.standing_still = true
end
function ENT:OnRemove()
SafeRemoveEntity(self.weld)
SafeRemoveEntity(self.csmodel)
end
function ENT:InAir()
if not self.next_in_air or self.next_in_air < RealTime() then
local point = self:GetPos()
local down = -self:GetUp()
local size = self:GetSize()
if bit.band(util.PointContents(point + down * size + down), CONTENTS_SOLID) == CONTENTS_SOLID then
self.in_air = false
else
self.trace_tbl = self.trace_tbl or {}
self.trace_tbl.output = self.trace_tbl
self.trace_tbl.start = point
self.trace_tbl.endpos = point
self.trace_tbl.mins = Vector(0.5,0.5,1) * -size
self.trace_tbl.maxs = Vector(0.5,0.5,0) * size
self.trace_tbl.filter = self
debugoverlay.Box(self.trace_tbl.start, self.trace_tbl.mins, self.trace_tbl.maxs, 0.1)
debugoverlay.Box(self.trace_tbl.endpos, self.trace_tbl.mins, self.trace_tbl.maxs, 0.1, Color(255,0,0,255))
util.TraceHull(self.trace_tbl)
if self.trace_tbl.Entity.ClassName == self.ClassName then
self.trace_tbl.Hit = false
end
self.in_air = not self.trace_tbl.Hit
end
self.next_in_air = RealTime() + 0.1
end
return self.in_air
end
function ENT:GetGroundTrace(distance)
self.ground_trace_cache = self.ground_trace_cache or {}
distance = distance or 15
self.ground_trace_cache[distance] = self.ground_trace_cache[distance] or {}
if self.ground_trace_cache[distance].next and self.ground_trace_cache[distance].next > RealTime() then
return self.ground_trace_cache[distance].res
end
local gravity_dir = physenv.GetGravity():GetNormalized()
local bottom = self:GetPos() + gravity_dir * (self:GetSize() * 1.7)
local res = util.TraceLine({
start = self:GetPos(),
endpos = bottom + gravity_dir * distance,
filter = self,
})
self.ground_trace_cache[distance].res = res
self.ground_trace_cache[distance].next = RealTime() + 0.2
return res
end
if CLIENT then
ENT.Cycle = 0
ENT.Noise = 0
local ambient_sounds = {
"ambient/creatures/seagull_idle1.wav",
"ambient/creatures/seagull_idle2.wav",
"ambient/creatures/seagull_idle3.wav",
}
local footstep_sounds = {}
for i = 1, 5 do
footstep_sounds[i] = "seagull_step_" .. i .. "_" .. util.CRC(os.clock())
sound.Generate(footstep_sounds[i], 22050, 0.25, function(t)
local f = (t/22050) * (1/0.25)
f = -f + 1
f = f ^ 10
return ((math.random()*2-1) * math.sin(t*1005) * math.cos(t*0.18)) * f
end)
end
local no_texture = Material("vgui/white")
function ENT:Draw()
if DEBUG then
render.SetMaterial(no_texture)
render.DrawSphere(self:GetPos(), self:GetSize(), 16, 16, self:InAir() and Color(0, 0, 255, 128) or Color(255, 0, 0, 128), true)
end
end
function ENT:Think()
local size = self:GetSize()
if size ~= self.last_size then
self.local_pos = Vector(0, 0, -size)
self.csmodel:SetColor(Color(255, 255, Lerp(size/20, 100, 255), 255))
self.csmodel:SetModelScale(size / self.csmodel:GetModelRadius() * 6)
self.last_size = size
end
if not self.next_vel or self.next_vel < RealTime() then
self.Velocity = (self:GetPos() - (self.last_pos or self:GetPos())) * 12
self.last_pos = self:GetPos()
self.next_vel = RealTime() + 1/15
end
self:AnimationThink()
self.csmodel:SetPos(self:GetPos() + self.local_pos)
self.csmodel:SetAngles(self:GetAngles())
if math.random() > 0.999 then
sound.Play(ambient_sounds[math.random(1, #ambient_sounds)], self:GetPos(), 75, math.Clamp((1000 / self:GetSize()) + math.Rand(-10, 10), 1, 255), 1)
end
if self.net_pos then
local dt = math.Clamp(FrameTime() * 5, 0.0001, 0.1)
local last_pos = self:GetPos()
local last_ang = self:GetAngles()
self:SetPos(LerpVector(dt, last_pos, self.net_pos))
self:SetAngles(LerpAngle(dt, last_ang, self.net_ang))
end
self:NextThink(CurTime() + 1/30)
return true
end
function ENT:SetAnim(anim)
self.csmodel:SetSequence(self.csmodel:LookupSequence(anim))
end
function ENT:AnimationThink()
local scale = self:GetSize()
local vel = self.Velocity / scale
local len = vel:Length()
local siz = scale*0.05
len = len / siz
if not self:InAir() then
self.takeoff = false
local mult = 1
if len < 1 then
self:SetAnim("Idle01")
len = 15 / siz * (self.Noise * 0.25)
else
if CLIENT then
self:StepSoundThink()
end
if len > 50 / siz then
self:SetAnim("Run")
else
self:SetAnim("Walk")
end
mult = math.Clamp(self:GetForward():Dot(vel), -1, 1)
end
self.Noise = (self.Noise + (math.Rand(-1,1) - self.Noise) * FrameTime())
self.Cycle = (self.Cycle + (len / (2.5 / siz)) * FrameTime() * mult) % 1
self.csmodel:SetCycle(self.Cycle)
else
local ground = self:GetGroundTrace(self:BoundingRadius() - 4)
if ground.Fraction < 1 then
local f = ground.Fraction
if vel.z > 0 then
if not self.takeoff then
self:SetAnim("Takeoff")
f = Lerp(f, 0.3, 0.4)
end
else
f = Lerp(f, 0.5, 0.8)
self:SetAnim("Land")
end
self.csmodel:SetCycle(f)
return
else
self.takeoff = true
end
if len < 50 then
self:SetAnim("Fly")
self.Cycle = self.Cycle + FrameTime() * 3.5 * (math.Rand(1, 1.1))
else
local fvel = self:GetRight():Dot(self.Velocity)
if math.abs(fvel) > 50 then
self:SetAnim("Fly")
self.Cycle = self.Cycle + FrameTime() * 0.5 * (math.Rand(1, 1.1))
else
if vel.z < 0 then
self:SetAnim("Soar")
self.Cycle = RealTime()
else
self:SetAnim("Fly")
if vel.z > 0 then
self.Cycle = self.Cycle + FrameTime() * 2
else
self.Cycle = Lerp(math.Clamp((-vel.z/100), 0, 1), 0.1, 1)
end
end
end
end
self.csmodel:SetCycle(self.Cycle)
end
end
function ENT:StepSoundThink()
local siz = self:GetSize()
local stepped = self.Cycle%0.5
if stepped < 0.3 then
if not self.stepped then
--[[sound.Play(
table.Random(sounds),
self:GetPos(),
math.Clamp(10 * siz, 70, 160),
math.Clamp(100 / (siz/3) + math.Rand(-20,20), 40, 255)
)]]
EmitSound(
table.Random(footstep_sounds),
self:GetPos(),
self:EntIndex(),
CHAN_AUTO,
1,
--math.Clamp(10 * siz, 70, 160),
55,
0,
--math.Clamp(100 / (siz/3) + math.Rand(-20,20), 40, 255)
math.Clamp(700/siz + math.Rand(-15, 15), 10, 255)
)
self.stepped = true
end
else
self.stepped = false
end
end
end
if SERVER then
local temp_vec = Vector()
local function VectorTemp(x,y,z)
temp_vec.x = x
temp_vec.y = y
temp_vec.z = z
return temp_vec
end
local flock_radius = 2000
local flock_pos
local food = {}
local tallest_points = {}
local all_seagulls = ents.FindByClass(ENT.ClassName)
local function global_update()
all_seagulls = ents.FindByClass(ENT.ClassName)
local found = all_seagulls
local count = #found
local pos = VectorTemp(0,0,0)
for _, ent in ipairs(found) do
local p = ent.Position or ent:GetPos()
pos = pos + p
end
if count > 1 then
pos = pos / count
flock_vel = (flock_pos or pos) - pos
flock_pos = pos
if DEBUG then
debugoverlay.Sphere(pos, flock_radius, 1, Color(0, 255, 0, 5))
if me:KeyDown(IN_JUMP) then
tallest_points = {}
end
end
local up = physenv.GetGravity():GetNormalized()
local top = util.QuickTrace(pos + Vector(0,0,flock_radius/2), up*-10000).HitPos
top.z = math.min(pos.z + flock_radius, top.z)
local bottom = util.QuickTrace(top, up*10000).HitPos
if DEBUG then
debugoverlay.Text(top, "TOP", 1)
debugoverlay.Text(bottom, "BOTTOM", 1)
debugoverlay.Text(LerpVector(0.5, top, bottom), "POINTS: " .. #tallest_points, 1)
end
top.z = math.min(flock_pos.z + flock_radius, top.z)
local max = 30
if not tallest_points[max] then
for i = 1, max do
if tallest_points[max] then
break
end
local start_pos = LerpVector(i/max, bottom, top)
if DBEUG then
debugoverlay.Cross(start_pos, 100, 1)
end
--if not util.IsInWorld(start_pos) then break end
local tr = util.TraceLine({
start = start_pos,
endpos = start_pos + VectorTemp(math.Rand(-1, 1), math.Rand(-1, 1), math.Rand(-1, -0.2))*flock_radius,
})
if tr.Hit and math.abs(tr.HitNormal.z) > 0.8 and (not tr.Entity:IsValid() or tr.Entity.ClassName ~= ENT.ClassName) then
if tr.HitPos.z > flock_pos.z then
for _,v in ipairs(tallest_points) do
if v:Distance(tr.HitPos) < 50 then
return
end
end
table.insert(tallest_points, tr.HitPos)
end
end
if DEBUG then
debugoverlay.Line(tr.StartPos, tr.HitPos, 1, tr.Hit and Color(0,255,0, 255) or Color(255,0,0, 255))
end
end
if DEBUG then
for _,v in ipairs(tallest_points) do
debugoverlay.Cross(v, 5, 1, Color(0,0,255, 255))
end
end
table.sort(tallest_points, function(a, b) return a.z > b.z end)
for i = #tallest_points, 1, -1 do
local v = tallest_points[i]
if v:Distance(flock_pos) > flock_radius then
table.remove(tallest_points, i)
end
end
end
else
flock_pos = nil
end
end
local function entity_create(ent)
timer.Simple(0.25, function()
if not ent:IsValid() then return end
local phys = ent:GetPhysicsObject()
if phys:IsValid() and (
phys:GetMaterial():lower():find("flesh") or
phys:GetMaterial() == "watermelon" or
phys:GetMaterial() == "antlion"
) then
ent.seagull_food = true
table.insert(food, ent)
end
end)
end
local function entity_remove(ent)
if ent.seagull_food then
for i,v in ipairs(food) do
if v == ent then
table.remove(food, i)
end
end
end
end
function ENT:OnTakeDamage(info)
print(self, info:GetDamage(), info:GetAttacker())
end
timer.Create(ENT.ClassName, 1, 0, function()
global_update()
end)
hook.Add("OnEntityCreated", ENT.ClassName, function(ent)
entity_create(ent)
end)
hook.Add("EntityRemoved", ENT.ClassName, function(ent)
entity_remove(ent)
end)
function ENT:Think()
local size = self:GetSize()
if size ~= self.last_size then
self:PhysicsInitSphere(size, "gmod_ice")
self:GetPhysicsObject():SetMass(size * 20)
self:SetCollisionBounds(Vector(-size, -size, -size), Vector(size, size, size))
self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE_DEBRIS)
self.last_size = size
end
if DEBUG2 then
if me:KeyDown(IN_ATTACK) then
self:MoveTo({
trace = me:GetEyeTrace(),
priority = 1,
id = "test",
finish = function()
self:GetPhysicsObject():Sleep()
end
})
end
if me:KeyDown(IN_RELOAD) then
for _,v in ipairs(all_seagulls) do
v:Remove()
end
end
if me:KeyDown(IN_ATTACK2) then
self:CancelMoving()
end
if me:KeyDown(IN_DUCK) then
if tallest_points[1] then
local point = table.remove(tallest_points, 1)
self.tallest_point_target = point
self:MoveTo({
pos = point,
})
end
end
end
if false and flock_pos then
if not self.tallest_point_target or (self.reached_target and math.random() > 0.2 and self.tallest_point_target.z < flock_pos.z - 100) then
if tallest_points[1] then
local point = table.remove(tallest_points, 1)
self.tallest_point_target = point
self:MoveTo({
pos = point,
})
end
end
if math.random() > 0.9 and flock_pos:Distance(self:GetPos()) > flock_radius then
self:MoveTo({
get_pos = function()
return flock_pos
end,
check = function()
return flock_pos:Distance(self:GetPos()) > flock_radius
end,
id = "flock",
})
end
end
if false and math.random() > 0.9 and not self.finding_food and not IsValid(self.weld) then
local ent = food[math.random(1, #food)] or NULL
if ent:IsValid() then
self.finding_food = true
local radius = self:BoundingRadius()
self:MoveTo({
check = function()
return
ent:IsValid() and
(
not IsValid(ent.seagull_weld) or
not IsValid(ent.seagull_weld.seagull) or
(ent.seagull_weld.seagull ~= self and ent.seagull_weld.seagull:GetSize() < self:GetSize())
)
end,
get_pos = function()
return ent:GetPos()
end,
priority = 1,
id = "food",
fail = function()
self.finding_food = nil
end,
finish = function()
self.finding_food = nil
local s = self:GetSize()
ent:SetPos(self:GetPos() + self:GetForward() * (s + 2) + self:GetUp() * s)
ent:GetPhysicsObject():EnableMotion(true)
local weld = constraint.Weld(self, ent, 0, 0, radius*500, true, false)
if weld then
ent:SetOwner(self)
self.weld = weld
self.weld.seagull = self
self.food = ent
ent.seagull_weld = weld
end
end,
})
end
end
local phys = self:GetPhysicsObject()
local fps = 10
self:PhysicsUpdate2(phys, 6)
if not self:InAir() and self.VelocityLength < 1 then
phys:Sleep()
end
self:CalcMoveTo()
self:NextThink(CurTime() + 1/fps)
return true
end
function ENT:AvoidOthers()
if not self.next_avoid or self.next_avoid < self.Time then
self.next_avoid = self.Time + math.random()*3
local pos = self.Position
local in_air = self:InAir()
local radius = self.Radius * (in_air and 5 or 2)
local average_pos = Vector()
local count = 0
for _, v in ipairs(all_seagulls) do
local pos2 = v.Position or v:GetPos()
--local radius2 = v.Radius or v:BoundingRadius()
if ((in_air and v:InAir()) or (not in_air and not v:InAir())) and pos2:Distance(pos) < (radius) then
average_pos = average_pos + pos2
count = count + 1
end
end
if count > 1 then
average_pos = average_pos / count
local vel = pos - average_pos
local len = vel:Length()
if len < 5 then return end
if not in_air then
vel.z = 0
end
if self.TargetPosition then
vel = vel * 0.5
else
self.damping_pause = self.damping_pause or 1
end
vel = vel * 1/len*10
self.NewVelocity = self.NewVelocity + vel
self.Velocityocity = self.NewVelocity
self.VelocityLength = self.Velocity:Length()
end
end
end
do -- move to a point
function ENT:MoveTo(data)
if data.check and not data.check() then if data.fail then data.fail() end return end
self.TargetPositions = self.TargetPositions or {}
self.reached_target = nil
self.target_ids = self.target_ids or {}
data.priority = data.priority or #self.TargetPositions + 1
if data.trace then
if data.trace.Entity:IsValid() then
data.trace.HitPosLocal = data.trace.Entity:WorldToLocal(data.trace.HitPos)
end
end
local id = data.id
if id and self.target_ids[id] then
table.Merge(self.target_ids[id], data)
for i,v in ipairs(self.TargetPositions) do
if v.id == id then
table.insert(self.TargetPositions, data.priority, table.remove(self.TargetPositions, i))
break
end
end
return
end
table.insert(self.TargetPositions, data.priority, data)
if id then
self.target_ids[id] = data
end
end
function ENT:CalcMoveTo()
if not self.TargetPositions then return end
local info = self.TargetPositions[1]
if info then
local ok = not info.check or info.check(self)
if ok then
local pos = info.pos
if info.get_pos then
pos = info.get_pos(self)
end
if info.trace then
if info.trace.Entity:IsValid() then
pos = info.trace.Entity:LocalToWorld(info.trace.HitPosLocal)
else
pos = info.trace.HitPos
end
end
local dir = pos - self.Position
local len = dir:Length()
if len > self.Radius then
self.TargetPosition = pos
self.reached_target = nil
self.standing_still = nil
elseif (self.VelocityLength < 100 and self.AngleVelocityLength < 100) then
if info.waiting_time then
self.standing_still = self.standing_still or self.Time + info.waiting_time
end
if not info.waiting_time or (self.standing_still < self.Time) then
self.TargetPosition = nil
self.standing_still = true
table.remove(self.TargetPositions, 1)
if info.id then
self.target_ids[info.id] = nil
end
self.reached_target = true
if info.finish then
info.finish()
end
end
end
else
if info.fail then
info.fail()
end
table.remove(self.TargetPositions, 1)
if info.id then
self.target_ids[info.id] = nil
end
self.TargetPosition = nil
self.reached_target = true
self.standing_still = true
end
end
end
function ENT:CancelMoving()
self.TargetPositions = {}
local info = self.TargetPositions[1]
if info then
if info.fail then info.fail() end
end
self.target_ids = {}
self.TargetPosition = nil
self.reached_target = true
self.standing_still = true
end
end
function ENT:CalcStuck()
if not self.standing_still then
if not self.unstuck_timer and self.VelocityLength < 10 then
if DEBUG then
debugoverlay.Text(self.Position, "STUCK?", 0.1)
end
self.stuck_timer = self.stuck_timer or self.Time + math.Rand(1.5,2)
if self.stuck_timer < self.Time then
self.Stuck = true
if DEBUG then
debugoverlay.Text(self.Position, "STUCK ", 1)
end
self.unstuck_timer = self.unstuck_timer or self.Time + math.Rand(0.5,1)
end
else
self.stuck_timer = nil
end
if self.unstuck_timer and self.unstuck_timer < self.Time then
self.Stuck = false
self.stuck_timer = nil
self.unstuck_timer = nil
if DEBUG then
debugoverlay.Text(self.Position, "UNSTUCK!", 1)
end
end
if self.Stuck then
return true
end
else
self.stuck_timer = nil
end
end
function ENT:CalcUpright()
local len = self.VelocityLength
local vel = self.Velocity * 1
if not self:InAir() then
vel.z = 0
end
local desired_ang = vel:Angle()
local ang = self.Physics:GetAngles()
local p = math.AngleDifference(desired_ang.p, ang.p)/180
local y = math.AngleDifference(desired_ang.y, ang.y)/180
local r = math.AngleDifference(desired_ang.r, ang.r)/180
local force = math.min(self:GetPhysicsObject():GetMass() * 0.5, 500)
if not self:InAir() then
force = force * math.Clamp(len-1, 0, 1)
if force == 0 then
self.Physics:SetAngles(Angle(0,ang.y,0))
end
end
self.NewAngleVelocity = Vector(force*r, force*p, force*y)
end
function ENT:CalcTargetPosition()
if self.TargetPosition then
if DEBUG then
debugoverlay.Line(self.TargetPosition, self.Position, 0)
end
self:PhysWake()
local dir = self.TargetPosition - self.Position
local dist = dir:Length()
local len = self.VelocityLength
local vel = dir:GetNormalized() * self.Physics:GetMass()/20
if self:InAir() then
vel.z = vel.z + self.Physics:GetMass()*0.01
end
if self:InAir() or dist > 200 then
if math.abs(dir.z) < 10 and not self:InAir() then
if len > 1000 then
vel.z = vel.z + 10
end
end
end
if self:InAir() then
if dir.z > -self:GetSize()*2 then
vel.z = vel.z + self:GetSize()
else
vel.z = vel.z + -self.Velocity.z * 0.05
end
end
self.NewVelocity = self.NewVelocity + vel
self.Velocity = self.NewVelocity
self.VelocityLength = self.NewVelocity:Length()
end
end
function ENT:CalcDamping()
-- damping
if self:InAir() then
-- slow down before hitting the ground
if self.Velocity.z < 0 and self:GetGroundTrace(5).Hit then
self.Physics:SetDamping(2, 0)
else
self.Physics:SetDamping(1, 0)
end
else
local mult = 1
if self.damping_pause then
self.damping_pause = math.max(self.damping_pause - FrameTime() * 1.5, 0)
mult = -self.damping_pause+1
if self.damping_pause == 0 then self.damping_pause = nil end
mult = mult ^ 5
end
self.Physics:SetDamping(5*mult, 5*mult)
end
--self.NewAngleVelocity = self.NewAngleVelocity + (-self.AngleVelocity * 0.05)
end
function ENT:PhysicsUpdate2(phys, mult)
self.Physics = phys
self.Velocity = phys:GetVelocity()
self.NewVelocity = Vector()
self.VelocityLength = self.Velocity:Length()
self.AngleVelocity = phys:GetAngleVelocity()
self.NewAngleVelocity = Vector()
self.AngleVelocityLength = self.AngleVelocity:Length()
self.Position = phys:GetPos()
self.Radius = self:BoundingRadius()
self.Time = RealTime()
self:AvoidOthers()
self:CalcTargetPosition()
self:CalcUpright()
--self:CalcAir()
if self:CalcStuck() then
self.NewVelocity = VectorRand() * 50
end
self:CalcDamping()
phys:AddVelocity(self.NewVelocity * mult)
phys:AddAngleVelocity(-self.AngleVelocity + (self.NewAngleVelocity * mult))
end
end
scripted_ents.Register(ENT, ENT.ClassName)
function CREATESEAGULLS(where, max)
for _ = 1, max or 30 do
local ent = ents.Create("monster_seagull")
ent:SetPos(where + Vector(math.Rand(-1,1), math.Rand(-1,1), 0)*100 + Vector(0,0,50))
ent:Spawn()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment