Jump to content

Recommended Posts

Posted

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

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.

×
×
  • Create New...