Jump to content

My Mortar Solution


burgelkat
 Share

Recommended Posts

Hi ,

i will share my solution for the Mortar.

image.png.f49014b35b6f6e3991b1fe37228c602a.png

image.png.19ccebf387fba15a000c1800d6f1dba7.png

Mortar = a Pivot put there this script in (MortarTracking.lua)

import "Scripts/Functions/ReleaseTableObjects.lua"
import "Scripts/Functions/GetEntityNeighbors.lua"

Script.enabled=true--bool "Enabled"
Script.trackingrange = 10
Script.tracking=false

function Script:Enable()--in
	if self.enabled==false then
		self.enabled=true
		self.component:CallOutputs("Enable")
	end
end

function Script:Disable()--in
	if self.enabled then
		self.enabled=false
		self.component:CallOutputs("Disable")
	end
end

function Script:UpdatePhysics()
if self.enabled then
   -- load entities within range (5000) of self.entity into "entities", only load entities that have scripts attached
   local entities = GetEntityNeighbors(self.entity,5000,true)
   local k,entity
   -- loop thrrough the result of "entities". k = key, entity = result
   for k,entity in pairs(entities) do
       -- only select entities with teamid == 1 ("good")
       if entity.script.teamid == 1 then
           -- and if the entity has at least 1 health remaining
           if entity.script.health>0 then
               local d = self.entity:GetDistance(entity)
            self.target = entity
			end			
				local pos = self.entity:GetPosition()
				local targetpos = self.target:GetPosition()
					--if math.abs(targetpos.y-pos.y)<1.5 then
						if pos:xz():DistanceToPoint(targetpos:xz())<self.trackingrange then
							self.tracking=false
						else	
							self.tracking=true							
						end
			end
		end

	if self.tracking==true then
		self.entity:Point(self.target,2,Time:GetSpeed()*1.5);
	end
	end
end

in Mortar Body = the Model put in the script (Mortar.lua)

import "Scripts/Functions/ReleaseTableObjects.lua"
import "Scripts/Functions/GetEntityNeighbors.lua"

Script.enabled=true--bool "Enabled"

--Public
Script.target = nil--enemy to shoot
Script.teamid=3--choice "Team" "Neutral,Good,Bad"
Script.range = 5000
Script.health=100
Script.projectilepath = "Prefabs/projectiles/MortarAmmo.pfb"

Script.shoot1sound=""--path "File" "All Supported Files:ogg,wav;Waveform Audio File Format (*.wav):wav;Ogg Vorbis (*.ogg):ogg|Sound"
Script.shoot2sound=""--path "File" "All Supported Files:ogg,wav;Waveform Audio File Format (*.wav):wav;Ogg Vorbis (*.ogg):ogg|Sound"
Script.shoot3sound=""--path "File" "All Supported Files:ogg,wav;Waveform Audio File Format (*.wav):wav;Ogg Vorbis (*.ogg):ogg|Sound"

--Private
Script.lastfiretime=0
Script.mode = "idle"
Script.lastsearchtime	= 0
Script.searchfrequency 	= 500
Script.firefrequency 	= 4000
Script.Force1 = Vec3(0,1500,0)
Script.Force2 = Vec3(0,2500,0)
Script.Force3 = Vec3(0,3000,0)
Script.Force4 = Vec3(0,3500,0)
Script.range0 = 20
Script.range1 = 30
Script.range2 = 60
Script.range3 = 90
Script.range4 = 110

function Script:Start()  
   --Load sounds
        self.sound = {}
        self.sound.shoot = {}
        if self.shoot1sound~="" then self.sound.shoot[1] = Sound:Load(self.shoot1sound) end
        if self.shoot2sound~="" then self.sound.shoot[2] = Sound:Load(self.shoot2sound) end
        if self.shoot3sound~="" then self.sound.shoot[3] = Sound:Load(self.shoot3sound) end

        self.projectile = Prefab:Load(self.projectilepath)
        if self.projectile~=nil then
            self.projectile:Hide()
        end
        self.Mortar = self.entity:FindChild("Mortar")
        --Add muzzleflash to gun
        self.muzzle = self.entity:FindChild("muzzle")
        if self.muzzle~=nil then
                local mtl=Material:Create()
                mtl:SetBlendMode(5)
                self.muzzle:SetMaterial(mtl)
                mtl:Release()
                self.muzzleflash = Sprite:Create()
                self.muzzleflash:SetSize(0.35,0.35)
                local pos=self.muzzle:GetPosition(true)
                self.muzzleflash:SetPosition(pos,true)
                self.muzzleflash:SetParent(self.muzzle,true)
                mtl = Material:Load("Materials/Effects/muzzleflash.mat")
                if mtl then
                        self.muzzleflash:SetMaterial(mtl)
                        mtl:Release()
                        mtl=nil
                end
                local light = PointLight:Create()
                light:SetRange(5)
                light:SetColor(1,0.75,0)
                light:SetParent(self.muzzleflash,flash)
                if light.world:GetLightQuality()<2 then
                        light:SetShadowMode(0)  
                end
                self.muzzleflash:Hide()
        end

end

function Script:Release()
        if self.projectile~=nil then
                self.projectile:Release()
                self.projectile = nil
        end
end

function MortarSearchHook(entity,extra)
        if entity~=extra then
                if entity.script~=nil then
					if entity.script.teamid == 1 then
                        if type(entity.script.health)=="number" then
                                if entity.script.health>0 then
                                        local d = extra:GetDistance(entity)
                                        if d<extra.script.range then
                                                if extra.script.target~=nil then
                                                        if extra.script:GetDistance(extra.script.target)>d then
                                                                if extra.script:GetTargetVisible(entity.script) then
                                                                        extra.script.target = entity.script
                                                                end
                                                        end
                                                else
                                                        if extra.script:GetTargetVisible(entity.script) then
                                                                extra.script.target = entity.script
                                                        end
                                                end
                                        end
                                end
                        end
                end
        end
end
end




function Script:GetTargetVisible(target)
        if target==nil then
                target = self.target
        end
        if target==nil then
	                return false			
        end
        local pickinfo = PickInfo()
        local p0 = self.entity:GetAABB().center
        local p1 = target.entity:GetAABB().center
        local pickmode0 = self.entity:GetPickMode()
        local pickmode1 = target.entity:GetPickMode()
        self.entity:SetPickMode(0)
        target.entity:SetPickMode(0)
        local result = not self.entity.world:Pick(p0,p1,pickinfo,0,false,Collision.LineOfSight)
        self.entity:SetPickMode(pickmode0)
        target.entity:SetPickMode(pickmode1)    
        return result
end


function Script:UpdateWorld()
if self.enabled==true then
        if self.health>=0 then
			self.component:CallOutputs("Online")
                local currenttime = Time:GetCurrent()

                --Stop shooting if target is dead
                if self.target~=nil then
                    if self.target.health<=0 then
						self.component:CallOutputs("Idle")
                        self.target = nil
                    end
                end
                --Search for target
				if self.enabled==true then
                if self.target==nil then
                    if currenttime - self.lastsearchtime > self.searchfrequency then
                        self.lastsearchtime = currenttime
                        local pos = self.entity:GetPosition(true)
                        local aabb = AABB(pos - Vec3(self.range), pos + Vec3(self.range))
                        self.entity.world:ForEachEntityInAABBDo(aabb,"MortarSearchHook",self.entity)
                    end
                end
				end
---------------------deactivated because the Mortar should fire if vegetation hides you-----------------		
                --Continuous visibility test
               --[[ if self.target~=nil then
                       if currenttime - self.lastsearchtime > self.searchfrequency then
                                self.lastsearchtime = currenttime
                                if self:GetTargetVisible(self.target)==false then
                                        self.target = nil
                                        return
                                end  
						end 
                end]]
----------------------------------------------------------------------------------------------------------
                if self.target~=nil then

---------------------------no need for this (i think)---------------------------------------------------------------
                        --[[Motion tracking
                        if self.Mortar~=nil then
                                local p0 = self.Mortar:GetPosition(true)
                                local p1 = self.target.entity:GetAABB().center
                                local yplane = p1 - p0
                                yplane.y=0
                                self.Mortar:AlignToVector(yplane,1,0.1 / Time:GetSpeed(),0)
                        end]]
----------------------------------------------------------------------------------------------------------
                        --Shoot
                        if self.muzzle~=nil and self.projectile~=nil then
                                if currenttime - self.lastfiretime > self.firefrequency then
                                        self.lastfiretime = currenttime
                                        local bullet = self.projectile:Instance()

                                        self.muzzleflash:Show()
                                        self.muzzleflash:EmitSound(self.sound.shoot[#self.sound.shoot])
                                        self.muzzleflash:SetAngle(math.random(0,360))
                                        self.muzzleflashtime=currenttime

                                        if bullet~=nil then												
                                                bullet:Show()												
												bullet:SetFriction(1000,1000)
												bullet:SetCollisionType(Collision.Projectile)
                                                bullet:SetPosition(self.muzzle:GetPosition(true),true)
                                                bullet:SetRotation(self.muzzle:GetRotation(true),true)
													targetpos = self.target.entity:GetPosition()
													pos1 = self.entity:GetPosition(true)
													--if math.abs(targetpos.y-pos1.y)<1.5 then
-------------------------------------------------Fire Range---------------------------------------------------------------------
														if pos1:xz():DistanceToPoint(targetpos:xz())<self.range1 then
															System:Print("1")
															bullet:AddForce(self.Force1)
														else
														if pos1:xz():DistanceToPoint(targetpos:xz())<self.range2 then
															System:Print("2")
															bullet:AddForce(self.Force2)
														else
														if pos1:xz():DistanceToPoint(targetpos:xz())<self.range3 then
															System:Print("3")
															bullet:AddForce(self.Force4)
														else
														if pos1:xz():DistanceToPoint(targetpos:xz())<self.range4 then
															System:Print("4")
															bullet:AddForce(self.Force4)														
														else
														return 100000
													end end	end end 
--------------------------------------------------------------------------------------------------------------------------------
												bullet:SetMass(0.4)
                                                if bullet.script~=nil then
                                                        bullet.script.owner = self
                                                        if type(bullet.script.Enable)=="function" then
                                                                bullet.script:Enable()
                                                        end
                                                        bullet:Turn(Math:Random(-4,4),Math:Random(-4,4),0)														
												end
                                        end
                                end
                        end
                end
end

 if self.health<=0 then
	self.component:CallOutputs("Offline")
end
    self:UpdateMuzzleFlash()
	end
end



function Script:UpdateMuzzleFlash()
        if self.muzzleflashtime then
                if Time:GetCurrent()-self.muzzleflashtime<30 then
                        self.muzzleflash:Show()
                else
                        self.muzzleflash:Hide()
                end
        end
end

function Script:Online()--in
	if self.enabled==false then
		self.component:CallOutputs("Online")
		self.enabled=true
	end
end

function Script:Offline()--in
	if self.enabled==true then
		self.component:CallOutputs("Offline")
		self.enabled=false
	end
end

 

for the Ammo

search a model like my on http://www.cadnav.com/3d-models/model-42383.html

and put the script "MortarAmmo" in

Script.movespeed=1000
Script.pickradius=0
Script.damage=10
Script.lifetime=20000
Script.enabled=false--bool "Enabled"

function Script:Start()
	self.sound={}	
	self.sound.ricochet={}
	self.sound.ricochet[1]=Sound:Load("Sound/Weapons/Explosion.wav")
	self.sound.ricochet[2]=Sound:Load("Sound/Weapons/Explosion.wav")
	self.sound.ricochet[3]=Sound:Load("Sound/Weapons/Explosion.wav")
	self.starttime=Time:GetCurrent()

	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]:SetCollisionType(Collision.Prop)--Enables particle bouncing
	self.emitter[0]:SetMaterial("Materials/Effects/smoke.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(5.5,15,5.5,1)
	self.emitter[0]:SetParticleCount(20)
	self.emitter[0]:SetReleaseQuantity(20)
	self.emitter[0]:SetMaxScale(0.9)
	self.emitter[0]:SetDuration(1500)
	self.emitter[0]:SetAcceleration(0,-12,0)
	self.emitter[0]:SetLoopMode(false)
	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(8)
	self.emitter[1]:SetReleaseQuantity(3)
	self.emitter[1]:SetMaxScale(15)
	self.emitter[1]:SetDuration(3800)
	self.emitter[1]:AddScaleControlPoint(0,0.5)
	self.emitter[1]:AddScaleControlPoint(1,1)
	self.emitter[1]:SetRotationSpeed(10)
	self.emitter[1]:SetLoopMode(false)
	self.emitter[1]:Hide()
	
	--Smoke emitter - This will provide a soft dust effect around bullet impacts
	self.emitter[2]=Emitter:Create()
	self.emitter[2]:SetColor(1,1,1,0.25)
	self.emitter[2]:SetMaterial("Prefabs/Effects/Explosion/explosion.mat")
	self.emitter[2]:SetEmissionVolume(0.1,0.1,0.1)
	self.emitter[2]:SetVelocity(0.3,0.3,0.3,1)
	self.emitter[2]:SetParticleCount(1)
	self.emitter[2]:SetReleaseQuantity(1)
	self.emitter[2]:SetMaxScale(25)
	self.emitter[2]:SetDuration(2500)
	self.emitter[2]:AddScaleControlPoint(0,0.5)
	self.emitter[2]:AddScaleControlPoint(1,1)
	self.emitter[2]:SetRotationSpeed(10)
	self.emitter[2]:SetLoopMode(false)
	self.emitter[2]:Hide()
end

function Script:Enable()
	if self.enabled==false then
		self.enabled=true
	end
end

function Script:FindScriptedParent(entity,func)
	while entity~=nil do
		if entity.script then
			if type(entity.script[func])=="function" then
				return entity
			end
		end
		entity = entity:GetParent()
	end
	return nil
end

function Script:UpdateWorld()
	if self.enabled==false then return end
	if self.entity:Hidden() then return end
	local pickinfo=PickInfo()	
	local pos = self.entity:GetPosition(true)
	local targetpos = Transform:Point(0,0,self.movespeed/60.0 * Time:GetSpeed(),self.entity,nil)
	local result = self.entity.world:Pick(pos,targetpos,pickinfo,self.pickradius,true,Collision.Projectile)
	if result then
		local enemy = self:FindScriptedParent(pickinfo.entity,"Hurt")
		if enemy then
			if self.owner then
				--if self.owner.teamid==enemy.script.teamid then
				--	result=false
				--end
			end
			if result then
				if enemy.script.health>0 then
					enemy.script:Hurt(self.damage,self.owner)
				end
			end	
		end
		if result then
			self:Explode()
			--Bullet mark decal
			local mtl
			local scale = 2
			if enemy~=nil then
				mtl = Material:Load("Materials/Decals/wound.mat")
				scale = 0.1
			else
				if pickinfo.surface~=nil then
					local pickedmaterial = pickinfo.surface:GetMaterial()
					if pickedmaterial~=nil then
						rendermode = pickedmaterial:GetDecalMode()
					end
				end
				mtl = Material:Load("Materials/Decals/BombCrater.mat")
			end
			local decal = Decal:Create(mtl)
			decal:AlignToVector(pickinfo.normal,2)
			decal:Turn(0,0,Math:Random(0,360))
			decal:SetScript("Scripts/Objects/Effects/BulletMark.lua")
			if mtl~=nil then mtl:Release() end
			decal:SetPosition(pickinfo.position)
			decal:SetParent(pickinfo.entity)
			
			--Apply global scaling
			local mat = decal:GetMatrix()
			mat[0] = mat[0]:Normalize() * scale
			mat[1] = mat[1]:Normalize() * scale
			mat[2] = mat[2]:Normalize() * scale	
			decal:SetMatrix(mat)
			decal:EmitSound(self.sound.ricochet[math.random(#self.sound.ricochet)],30)

			self.entity:Release()
		else
			self.entity:SetPosition(targetpos)
		end
	else
		self.entity:SetPosition(targetpos)
	end
	if Time:GetCurrent()-self.starttime>self.lifetime then
		self.entity:Release()
	end
end

function Script:Explode()
	self.entity:EmitSound(self.sound.ricochet[math.random(#self.sound.ricochet)],30)
	self.emitter[0]:Show()
	self.emitter[0]:SetPosition(self.entity:GetPosition(true))
	self.emitter[0]:Reset()
	self.emitter[0]:Play()	
	self.emitter[1]:Show()
	self.emitter[1]:Reset()
	self.emitter[1]:SetPosition(self.entity:GetPosition(true))
	self.emitter[1]:Play()
	self.emitter[2]:Show()
	self.emitter[2]:Reset()
	self.emitter[2]:SetPosition(self.entity:GetPosition(true))
	self.emitter[2]:Play()
end

function Script:Collision(entity, position, normal, speed)	
	self:Explode()
end

 

ok so far so good i hope you have fun.

at the moment i think the scripts can be better written... for sure the Ammo script

because it use the raycast to detect impact.  i build in a collision line additional but this is not a perfect solution

because the decal works only on pick

ok changes from you are welcome in this post

 

 

  • Upvote 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...