http://www.mediafire.com/download/ipr281l5cqxoui1/gladiouse.fbx weapon file
http://www.mediafire.com/download/k1fnvksheltgn3m/harpy.fbx monster
Monster code
import "Scripts/AnimationManager.lua"
import "Scripts/Functions/GetEntityNeighbors.lua"
--Public values
Script.health=40--int "Health"
Script.enabled=true--bool "Enabled"
Script.target=nil--entity "Target"
Script.sightradius=30--float "Sight Range"
Script.senseradius=2--float "Hearing Range"
Script.teamid=2--choice "Team" "Neutral,Good,Bad"
--Private values
Script.damage=5
Script.attackrange=1.5
Script.updatefrequency=500
Script.lastupdatetime=0
Script.prevtarget=nil
Script.animation={}
Script.animation.idle=1
Script.animation.run=2
Script.animation.attack={}
Script.animation.attack[0]=4
Script.animation.attack[1]=2
Script.animation.death=3
Script.followingtarget=false
Script.maxaccel=10
Script.speed=6
Script.lastupdatetargettime=0
Script.attackmode=0
Script.attackbegan=0
Script.sound={}
Script.sound.alert = Sound:Load("Sound/Characters/mutant_injure_02.wav")
Script.sound.attack={}
Script.sound.attack[1] = Sound:Load("Sound/Characters/mutant_attack_04.wav")
Script.sound.attack[2] = Sound:Load("Sound/Characters/mutant_attack_06.wav")
function Script:Enable()--in
if self.enabled==false then
if self.health>0 then
self.enabled=true
if self.target~=nil then
self:SetMode("roam")
else
self:SetMode("idle")
end
end
end
end
function Script:ChooseTarget()
local entities = GetEntityNeighbors(self.entity,self.sightradius,true)
local k,entity
for k,entity in pairs(entities) do
if entity.script.teamid~=nil and entity.script.teamid~=0 and entity.script.teamid~=self.teamid then
if entity.script.health>0 then
local d = self.entity:GetDistance(entity)
--if d<self.senseradius then
-- return entity.script
--else
-- local p = Transform:Point(entity:GetPosition(),nil,self.entity)
-- if (p.z>-math.abs(p.x) and p.z<-math.abs(p.y)) then
local pickinfo=PickInfo()
if self.entity.world:Pick(self.entity:GetPosition()+Vec3(0,1.6,0),entity:GetPosition()+Vec3(0,1.6,0),pickinfo,0,false,Collision.LineOfSight)==false then
return entity.script
end
-- end
--end
end
end
end
end
function Script:DistanceToTarget()
local pos = self.entity:GetPosition()
local targetpos = self.target.entity:GetPosition()
if math.abs(targetpos.y-pos.y)<1.5 then
return pos:xz():DistanceToPoint(targetpos:xz())
else
return 100000--if they are on different vertical levels, assume they can't be reached
end
end
function Script:TargetInRange()
local pos = self.entity:GetPosition()
local targetpos = self.target.entity:GetPosition()
if math.abs(targetpos.y-pos.y)<1.5 then
if pos:xz():DistanceToPoint(targetpos:xz())<self.attackrange then
return true
end
end
return false
end
function WorldGetEntitiesInAABBDoCallback(entity,extra)
if entity~=extra then
if GetEntityNeighborsScriptedOnly==false or entity.script~=nil then
table.insert(WorldGetEntitiesInAABBDoCallbackTable,entity)
end
end
end
function GetEntityNeighbors(entity,radius,scriptOnly)
local result
local aabb = AABB()
local p = entity:GetPosition(true)
local temp = GetEntityNeighborsScriptedOnly
GetEntityNeighborsScriptedOnly=scriptOnly
aabb.min = p - radius
aabb.max = p + radius
aabb:Update()
local table = WorldGetEntitiesInAABBDoCallbackTable
WorldGetEntitiesInAABBDoCallbackTable = {}
entity.world:ForEachEntityInAABBDo(aabb,"WorldGetEntitiesInAABBDoCallback",entity)
result = WorldGetEntitiesInAABBDoCallbackTable
WorldGetEntitiesInAABBDoCallbackTable = table
GetEntityNeighborsScriptedOnly = temp
return result
end
function Script:Start()
self.animationmanager = AnimationManager:Create(self.entity)
if self.enabled then
if self.target~=nil then
self:SetMode("roam")
else
self:SetMode("idle")
end
end
end
function Script:Hurt(damage,distributorOfPain)
if self.health>0 then
if self.target==nil then
self.target=distributorOfPain
self:SetMode("attack")
end
self.health = self.health - damage
if self.health<=0 then
self.entity:SetMass(0)
self.entity:SetCollisionType(0)
self.entity:SetPhysicsMode(Entity.RigidBodyPhysics)
self:SetMode("dying")
end
end
end
function Script:EndDeath()
self:SetMode("dead")
end
function Script:DirectMoveToTarget()
self.entity:Stop()
local targetpos = self.target.entity:GetPosition()
local pos = self.entity:GetPosition()
local dir = Vec2(targetpos.z-pos.z,targetpos.x-pos.x):Normalize()
local angle = -Math:ATan2(dir.y,-dir.x)
self.entity:SetInput(angle,self.speed)
end
function Script:SetMode(mode)
if mode~=self.mode then
local prevmode=self.mode
self.mode=mode
if mode=="idle" then
self.target=nil
self.animationmanager:SetAnimationSequence(0,0.02)
self.entity:Stop()--stop following anything
elseif mode=="roam" then
if self.target~=nil then
self.animationmanager:SetAnimationSequence(1,0.04)
self.entity:GoToPoint(self.target:GetPosition(true),5,5)
else
self:SetMode("idle")
end
elseif mode=="attack" then
self:EndAttack()
elseif mode=="chase" then
if self.entity:Follow(self.target.entity,self.speed,self.maxaccel) then
if prevmode~="chase" then
self.entity:EmitSound(self.sound.alert)
end
self.followingtarget=true
self.animationmanager:SetAnimationSequence(self.animation.run,0.05,300)
if self:DistanceToTarget()<self.attackrange*2 then
self.followingtarget=false
self.entity:Stop()
self:DirectMoveToTarget()
end
else
self.target=nil
self:SetMode("idle")
return
end
elseif mode=="dying" then
self.entity:Stop()
self.animationmanager:SetAnimationSequence(self.animation.death,0.04,300,1,self,self.EndDeath)
elseif mode=="dead" then
self.entity:SetCollisionType(0)
self.entity:SetMass(0)
self.entity:SetShape(nil)
self.entity:SetPhysicsMode(Entity.RigidBodyPhysics)
self.enabled=false
end
end
end
function Script:EndAttack()
if self.mode=="attack" then
if self.target.health<=0 then
self:SetMode("idle")
return
end
local d = self:DistanceToTarget()
if d>self.attackrange then
--if d>self.attackrange*2 then
self:SetMode("chase")
return
--else
-- local pos = self.entity:GetPosition()
-- local targetpos = self.target.entity:GetPosition()
-- self.entity:SetInput(-Math:ATan2(targetpos.x-pos.x,targetpos.y-pos.y),self.speed)
-- return
--end
end
self.entity:Stop()
self.attackmode = 1-self.attackmode--switch between right and left attack modes
self.animationmanager:SetAnimationSequence(self.animation.attack[self.attackmode],0.04*math.random(1,1.25),300,1,self,self.EndAttack)
self.attackbegan = Time:GetCurrent()
if math.random()>0.75 then self.entity:EmitSound(self.sound.attack[self.attackmode+1]) end
end
end
function Script:UpdatePhysics()
if self.enabled==false then return end
local t = Time:GetCurrent()
self.entity:SetInput(self.entity:GetRotation().y,0)
if self.mode=="idle" then
if t-self.lastupdatetargettime>250 then
self.lastupdatetargettime=t
self.target = self:ChooseTarget()
if self.target then
self:SetMode("chase")
end
end
elseif self.mode=="roam" then
if self.entity:GetDistance(self.target)<1 then
self:SetMode("idle")
end
elseif self.mode=="chase" then
if self.target.health<=0 then
self:SetMode("idle")
return
end
if self:TargetInRange() then
self:SetMode("attack")
elseif self:DistanceToTarget()<self.attackrange*2 then
self.followingtarget=false
self.entity:Stop()
self:DirectMoveToTarget()
else
if self.followingtarget==false then
if self.entity:Follow(self.target.entity,self.speed,self.maxaccel) then
self:SetMode("idle")
end
end
end
elseif self.mode=="attack" then
if self.attackbegan~=nil then
if t-self.attackbegan>300 then
self.attackbegan=nil
self.target:Hurt(self.damage)
end
end
local pos = self.entity:GetPosition()
local targetpos = self.target.entity:GetPosition()
local dx=targetpos.x-pos.x
local dz=targetpos.z-pos.z
self.entity:AlignToVector(-dx,0,-dz)
end
end
function Script:Draw()
if self.enabled==false then return end
self.animationmanager:Update()
end
weapon code
import "Scripts/AnimationManager.lua"
Script.offset=Vec3(0,0,0)--Vec3 "Offset"
Script.clipsize=6--int "Clip size"
Script.ammo=200--int "Ammunition"
Script.maxswayamplitude=0.01
Script.amplitude=0
Script.swayspeed=0
Script.timeunits=0
Script.smoothedposition=Vec3(0)
Script.smoothedrotation=Vec3(0)
Script.verticalbob=0
Script.jumpoffset=0
Script.landoffset=0
Script.firetime=0
Script.bulletrange=1000
Script.bulletforce=500
Script.bulletdamage=10
Script.reloading=false
Script.clipammo=Script.clipsize
Script.dryfiresoundfile=""--path "Dry fire" "Wav File (*wav):wav|Sound"
Script.fire1soundfile=""--path "Fire sound 1" "Wav File (*wav):wav|Sound"
Script.fire2soundfile=""--path "Fire sound 2" "Wav File (*wav):wav|Sound"
Script.fire3soundfile=""--path "Fire sound 3" "Wav File (*wav):wav|Sound"
Script.ricochet1soundfile=Sound:Load("Sound/Ricochet/bullet_impact_dirt_01.wav")
Script.ricochet2soundfile=Sound:Load("Sound/Ricochet/bullet_impact_dirt_02.wav")
Script.ricochet3soundfile=Sound:Load("Sound/Ricochet/bullet_impact_dirt_03.wav")
Script.reloadsoundfile=""--path "Reload sound" "Wav File (*wav):wav|Sound"
function Script:Start()
self.ammo = self.ammo - self.clipammo
self.sound={}
if self.sound.dryfiresoundfile~="" then self.sound.dryfire=Sound:Load(self.dryfiresoundfile) end
self.sound.fire={}
if self.sound.fire1soundfile~="" then self.sound.fire[0]=Sound:Load(self.fire1soundfile) end
if self.sound.fire2soundfile~="" then self.sound.fire[1]=Sound:Load(self.fire2soundfile) end
if self.sound.fire3soundfile~="" then self.sound.fire[2]=Sound:Load(self.fire3soundfile) end
if self.reloadsoundfile~="" then
self.sound.reload=Sound:Load(self.reloadsoundfile)
end
self.sound.ricochet={}
self.sound.ricochet[0]=Sound:Load("Sound/Ricochet/bullet_impact_dirt_01.wav")
self.sound.ricochet[1]=Sound:Load("Sound/Ricochet/bullet_impact_dirt_02.wav")
self.sound.ricochet[2]=Sound:Load("Sound/Ricochet/bullet_impact_dirt_03.wav")
self.entity:SetPickMode(0)
self.muzzleflash = Model:Load("Models/Primitives/Plane.mdl")
self.muzzleflash:SetCollisionType(0)
local material = Material:Load("Materials/Effects/muzzleflash.mat")
self.muzzleflash:SetMaterial(material)
self.muzzleflash:SetScale(0.25)
self.muzzlelight = PointLight:Create()
self.muzzlelight:SetColor(1,0.75,0)
self.muzzlelight:SetRange(4)
self.muzzleflash:SetShadowMode(0)
local tag = self.entity:FindChild("j_gun")
self.muzzlelight:SetParent(tag)
self.muzzlelight:SetPosition(0,0.2,0.5)
self.muzzlelight:Hide()
self.muzzleflash:SetParent(self.muzzlelight,false)
self.animationmanager = AnimationManager:Create(self.entity)
self.originalposition = self.entity:GetPosition()
self.originalrotation = self.entity:GetRotation()
self.emitter={}
--Debris emitter - This will throw chunks off of walls and make it look like they are breaking
self.emitter[0]=Emitter:Create()
self.emitter[0]:SetMaterial("Materials/Effects/default.mat")
self.emitter[0]:SetEmissionVolume(0.05,0.05,0.05)
self.emitter[0]:SetColor(0.1,0.1,0.1,1)
self.emitter[0]:SetVelocity(1.5,1.5,1.5,1)
self.emitter[0]:SetParticleCount(10)
self.emitter[0]:SetReleaseQuantity(10)
self.emitter[0]:SetMaxScale(0.3)
self.emitter[0]:SetDuration(1000)
self.emitter[0]:SetAcceleration(0,-12,0)
self.emitter[0]:Hide()
--Smoke emitter - This will provide a soft dust effect around bullet impacts
self.emitter[1]=Emitter:Create()
self.emitter[1]:SetColor(1,1,1,0.25)
self.emitter[1]:SetMaterial("Materials/Effects/smoke.mat")
self.emitter[1]:SetEmissionVolume(0.1,0.1,0.1)
self.emitter[1]:SetVelocity(0.3,0.3,0.3,1)
self.emitter[1]:SetParticleCount(3)
self.emitter[1]:SetReleaseQuantity(3)
self.emitter[1]:SetMaxScale(4)
self.emitter[1]:SetDuration(2500)
self.emitter[1]:AddScaleControlPoint(0,0.5)
self.emitter[1]:AddScaleControlPoint(1,1)
self.emitter[1]:SetRotationSpeed(10)
self.emitter[1]:Hide()
--Blood emitter - This will provide a visual cue when an enemy is shot
self.emitter[2]=self.emitter[1]:Instance()
self.emitter[2] = tolua.cast(self.emitter[2],"Emitter")
self.emitter[2]:SetMaterial("Materials/Effects/bloodspatter.mat")
self.emitter[2]:SetColor(1,1,1,0.25)
self.emitter[2]:SetParticleCount(3)
self.emitter[2]:SetReleaseQuantity(3)
self.emitter[2]:SetDuration(200)
self.emitter[2]:SetEmissionVolume(0,0,0)
self.emitter[2]:SetMaxScale(1)
self.emitter[2]:SetRotationSpeed(10)
self.emitter[2]:AddScaleControlPoint(0,0)
self.emitter[2]:AddScaleControlPoint(1,1)
self.emitter[2]:SetVelocity(0,0,0,0)
self.emitter[2]:SetVelocity(0,0,0,1)
self.emitter[2]:Hide()
end
function Script:Hide()
self.entity:Hide()
self.muzzleflash:Hide()
self.muzzlelight:Hide()
end
function Script:FindScriptedParent(entity,func)
while entity~=nil do
if entity.script then
if type(entity.script[func])=="function" then
if entity.script.enabled~=false then
return entity
else
return nil
end
end
end
entity = entity:GetParent()
end
return nil
end
function Script:BeginJump()
self.jumpoffset = -180
end
function Script:BeginLand()
self.landoffset = -180
end
function Script:EndReload()
self.reloading=false
local rounds = self.clipsize - self.clipammo
rounds = math.min(self.ammo,rounds)
self.ammo = self.ammo - rounds
self.clipammo = self.clipammo + rounds
end
function Script:Reload()
if self.clipammo<self.clipsize and self.ammo>0 and self.reloading~=true then
self.reloading=true
self.animationmanager:SetAnimationSequence(0,0.02,300,1,self,self.EndReload,25)
self.reloadstarttime=Time:GetCurrent()
if self.sound.reload~=nil then self.sound.reload:Play() end
end
end
function Script:Fire()
if self.reloading==false then
if self.clipammo==0 then
self.sound.dryfire:Play()
else
self.sound.fire[math.random(#self.sound.fire)]:Play()
self.clipammo = self.clipammo - 1
self.firetime = Time:GetCurrent()
self.muzzlelight:Point(self.player.camera,1)
self.muzzlelight:Turn(0,math.random(0,360),0)
self.muzzlelight:Show()
self.animationmanager:SetAnimationSequence(2,0.08,300,1)
local d = Transform:Normal(0,0,1,self.entity,nil)
local p = self.player.camera:GetPosition(true)
local pickinfo=PickInfo()
if self.entity.world:Pick(p,p+d*self.bulletrange,pickinfo,0,true,Collision.Prop) then
--Find first parent with the Hurt() function
local enemy = self:FindScriptedParent(pickinfo.entity,"Hurt")
if enemy~=nil then
if enemy.script.health>0 then
enemy.script:Hurt(self.bulletdamage,self.player)
end
--Blood emitter
e = self.emitter[2]:Instance()
e = tolua.cast(e,"Emitter")
e:Show()
e:SetLoopMode(false,true)
e:SetPosition(pickinfo.position+pickinfo.normal*0.1)
e:SetVelocity(0,0,0)
else
--Add a temporary particle emitter for bullet effects
local e
e = self.emitter[0]:Instance()
e = tolua.cast(e,"Emitter")
e:Show()
e:SetLoopMode(false,true)
e:SetPosition(pickinfo.position)
local v=3
e:SetVelocity(pickinfo.normal.x*v,pickinfo.normal.y*v,pickinfo.normal.z*v,0)
--Smoke emitter
e = self.emitter[1]:Instance()
e = tolua.cast(e,"Emitter")
e:Show()
e:SetLoopMode(false,true)
e:SetPosition(pickinfo.position+pickinfo.normal*0.1)
local v=0.2
e:SetVelocity(pickinfo.normal.x*v,pickinfo.normal.y*v,pickinfo.normal.z*v,0)
--Play bullet impact noise
e:EmitSound(self.sound.ricochet[math.random(#self.sound.ricochet)])
if pickinfo.entity~=nil then
--Add impulse to the hit object
if pickinfo.entity:GetMass()>0 then
--local force = pickinfo.normal*-1*self.bulletforce
local force = d * self.bulletforce * math.max(0,-pickinfo.normal:Dot(d))
--force = force * math.max(0,-pickinfo.normal:Dot(d))--multiply by dot product of velocity and collided normal, to weaken glancing blows
pickinfo.entity:AddPointForce(force,pickinfo.position)
end
--Extract a partial surface from the hit surface and make a bullet mark
--To be added later
if pickinfo.surface~=nil then
--local aabb = AABB(pickinfo.position-radius,pickinfo.position+radius)
--local surf = pickinfo.surface:Extract(aabb)
end
end
end
end
end
end
end
function Script:Draw()
local t = Time:GetCurrent()
if self.muzzlelight:Hidden()==false then
if t-self.firetime>50 then
self.muzzlelight:Hide()
end
end
local jumpbob = 0
if self.jumpoffset<0 then
jumpbob = (Math:Sin(self.jumpoffset))*0.01
self.jumpoffset = self.jumpoffset + 8
end
if self.landoffset<0 then
jumpbob = jumpbob + (Math:Sin(self.landoffset))*0.01
self.landoffset = self.landoffset + 10
end
--Animate the weapon
local bob = 0;
local speed = math.max(0.1,self.player.entity:GetVelocity():xz():Length())
if self.player.entity:GetAirborne() then speed = 0.1 end
self.swayspeed = Math:Curve(speed,self.swayspeed,20)
self.swayspeed = math.max(0.5,self.swayspeed)
self.amplitude = math.max(2,Math:Curve(speed,self.amplitude,20))
self.timeunits = self.timeunits + self.swayspeed*4*Time:GetSpeed()
local sway = math.sin(self.timeunits/120.0) * self.amplitude * self.maxswayamplitude
bob = (1-math.cos(self.timeunits/60.0)) * self.maxswayamplitude * 0.1 * self.amplitude
local campos = self.player.camera:GetPosition(true)
self.smoothedposition.x = campos.x
self.smoothedposition.y = Math:Curve(campos.y,self.smoothedposition.y,2)
self.smoothedposition.z = campos.z
self.entity:LockMatrix()
self.entity:SetPosition(sway*self.entity.scale.x,bob+jumpbob,0)
self.entity:Translate(self.offset.x,self.offset.y,self.offset.z)
self.animationmanager:Update()
self.entity:UnlockMatrix()
end
function Script:Release()
self.emitter[0]:Release()
self.emitter[1]:Release()
self.emitter=nil
end
those are what I have. Any idea what I am doing wrong? (side note should I reduce the polys on the monster?)