Jump to content

havenphillip

Members
  • Content Count

    222
  • Joined

  • Last visited

Community Reputation

37 Excellent

About havenphillip

  • Rank
    Advanced Member

Profile Information

  • Gender
    Male

Recent Profile Visitors

811 profile views
  1. You might want to post the script where this error is occurring so people can look through it for themselves. It's difficult to see what the number comparing with nil is: attemp to compare number with nil Line 8 If you're using my pickup script from above I might have changed something and that might be a different error. I would troubleshoot it by making sure that: 1. Maybe in your player script, under the Start() function you want to add: self.entity:SetKeyValue("type","player") 2. Your gun script has these at the top somewhere: Script.clipsize=6--int "Clip size" Script.ammo=200--int "Ammunition" Script.maxammo = 200 -- int "Max Ammo" 3. Your gun script has this in the Start() function: self.clipammo=self.clipsize self.ammo = self.ammo - self.clipammo self.muzzle = self.entity:FindChild("muzzle") This is the vwep gun script I use with that ammo pickup script. I don't remember if I changed anything: --import "Scripts/AnimationManager.lua" Script.index=1--int "Weapon slot" Script.offset=Vec3(0,0,0)--Vec3 "Offset" Script.rotation=Vec3(0,0,0)--Vec3 "Rotation" Script.clipsize=6--int "Clip size" Script.ammo=200--int "Ammunition" Script.maxammo = 200 -- int "Max Ammo" 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.bulletspeed=200--float "Bullet speed" Script.landoffset=0 Script.pellets=1--int "Pellets" Script.scatter=0.01--float "Scatter" Script.firetime=0 Script.refirerate=100--int "Refire rate" Script.bulletrange=1000 Script.muzzleflashscale=0.2--float "Flash size" Script.bulletforce=500--float "Force" Script.bulletdamage=10--int "Damage" Script.automatic=true--bool "Automatic" 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.pumpsoundfile=""--path "Pump sound" "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" Script.reloadspeed=0.05--float "Reload speed" Script.firespeed=0.05--float "Fire speed" Script.tracer = Sprite:Create() Script.tracer:Hide() Script.currentaction=nil function Script:Start() if self.started then return end self.started=true self.entity:SetPickMode(0,true) self.entity:SetAnimationFrame(0,1,"fire") self.entity:Hide() self.bullets = {} self.entity:SetShadowMode(0) self.entity:SetOcclusionCullingMode(false) self.tracer:SetViewMode(6)--Rotate around z axis self.tracer:SetSize(0.1,2) local mtl = Material:Load("Materials/Effects/tracer.mat") if mtl then self.tracer:SetMaterial(mtl) mtl:Release() end self.currentaction=nil self.clipammo=self.clipsize self.ammo = self.ammo - self.clipammo self.muzzle = self.entity:FindChild("muzzle") self.sound={} if self.sound.dryfiresoundfile~="" then self.sound.dryfire=Sound:Load(self.dryfiresoundfile) end self.sound.fire={} if self.pumpsoundfile~="" then self.sound.pump=Sound:Load(self.pumpsoundfile) end if self.fire1soundfile~="" then self.sound.fire[1]=Sound:Load(self.fire1soundfile) end if self.fire2soundfile~="" then self.sound.fire[2]=Sound:Load(self.fire2soundfile) end if self.fire3soundfile~="" then self.sound.fire[3]=Sound:Load(self.fire3soundfile) end if self.reloadsoundfile~="" then self.sound.reload=Sound:Load(self.reloadsoundfile) end self.sound.ricochet={} self.sound.ricochet[1]=Sound:Load("Sound/Ricochet/bullet_impact_dirt_01.wav") self.sound.ricochet[2]=Sound:Load("Sound/Ricochet/bullet_impact_dirt_02.wav") self.sound.ricochet[3]=Sound:Load("Sound/Ricochet/bullet_impact_dirt_03.wav") self.entity:SetPickMode(0) self.muzzleflash = Sprite:Create() self.muzzleflash:SetSize(self.muzzleflashscale,self.muzzleflashscale) self.muzzleflash:SetCollisionType(0) local material = Material:Load("Materials/Effects/muzzleflash.mat") self.muzzleflash:SetMaterial(material) self.muzzlelight = PointLight:Create() self.muzzlelight:SetColor(1,0.75,0) self.muzzlelight:SetRange(4) self.muzzleflash:SetShadowMode(0) local tag = self.entity:FindChild("muzzle") self.muzzlelight:SetParent(tag) self.muzzlelight:SetPosition(0,0,0) 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]:SetCollisionType(Collision.Prop)--Enables particle bouncing 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(5) self.emitter[0]:SetReleaseQuantity(5) self.emitter[0]:SetMaxScale(0.3) self.emitter[0]:SetDuration(1500) 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() --[[if self.autogive then local player,n for n,player in ipairs(players) do player:AddWeapon(self,self.index) end end]]-- self.entity:Hide() end function Script:Holster() if self.entity:FindAnimationSequence("holster")>-1 then --self.animationmanager:SetAnimationSequence("holster",self.reloadspeed,0,1)--,self,self.EndHolster,25) self.entity:PlayAnimation("holster",self.reloadspeed,0,1) end end function Script:Unholster() if self.entity:FindAnimationSequence("unholster")>-1 then --self.animationmanager:SetAnimationSequence("unholster",self.reloadspeed,0,1) self.entity:PlayAnimation("unholster",self.reloadspeed,0,1) self.currentaction="unholster" end end function Script:Hide() self.entity: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:FinalizeReload() self.currentaction=nil if self.cancelreload then self.cancelreload=false end end function Script:EndReload() if self.entity:FindAnimationSequence("ReloadLoop")>-1 then if self.ammo>0 and self.clipammo<self.clipsize and (self.reloadedshells==0 or self.cancelreload==false) then if self.sound.reload~=nil then self.sound.reload:Play() end --self.animationmanager:SetAnimationSequence("ReloadLoop",self.reloadspeed,300,1,self,self.EndReload) self.entity:PlayAnimation("ReloadLoop",self.reloadspeed,300,1,"EndReload") self.clipammo = self.clipammo + 1 self.ammo = self.ammo - 1 self.reloadedshells = self.reloadedshells + 1 else --self.animationmanager:SetAnimationSequence("ReloadEnd",self.reloadspeed,300,1,self,self.FinalizeReload) self.entity:PlayAnimation("ReloadEnd",self.reloadspeed,300,1,"FinalizeReload") end else self.currentaction=nil local rounds = self.clipsize - self.clipammo rounds = math.min(self.ammo,rounds) self.ammo = self.ammo - rounds self.clipammo = self.clipammo + rounds end end function Script:CanReload() if self.currentaction==nil then return true else return false end end function Script:Reload() if self.currentaction==nil then self.cancelreload=false if self.clipammo<self.clipsize and self.ammo>0 and self.currentaction==nil then self.currentaction="reload" self.reloadedshells=0 if self.entity:FindAnimationSequence("Reload")>-1 then --self.animationmanager:SetAnimationSequence("Reload",self.reloadspeed,300,1,self,self.EndReload) self.entity:PlayAnimation("Reload",self.reloadspeed,300,1,"EndReload") self.reloadstarttime=Time:GetCurrent() if self.sound.reload~=nil then self.sound.reload:Play() end elseif self.entity:FindAnimationSequence("ReloadStart")>-1 then --self.animationmanager:SetAnimationSequence("ReloadStart",self.reloadspeed,300,1,self,self.EndReload) self.entity:PlayAnimation("ReloadStart",self.reloadspeed,300,1,"EndReload") end end end end function Script:FinalizeFire() self.currentaction=nil end function Script:EndFire() if self.entity:FindAnimationSequence("Pump")>-1 then --self.animationmanager:SetAnimationSequence("Pump",0.03,300,1,self,self.FinalizeFire) self.entity:PlayAnimation("Pump",0.03,300,1,"FinalizeFire") if self.sound.pump~=nil then self.sound.pump:Play() end else self.currentaction=nil end end function Script:UpdateWorld() local bullet,n,dist local pickinfo=PickInfo() local firstbullet=true local travel for n,bullet in ipairs(self.bullets) do --Check how far the bullet has travelled dist = (bullet.position-bullet.origin):Length() if dist>self.bulletrange then table.remove(self.bullets,n) bullet.sprite:Release() bullet=nil end if bullet~=nil then travel = bullet.velocity/60.0*Time:GetSpeed() if self.entity.world:Pick(bullet.position,bullet.position+travel,pickinfo,0,true,Collision.Projectile) then --Find first parent with the Hurt() function local enemy = self:FindScriptedParent(pickinfo.entity,"Hurt") --local sph = Model:Sphere() --sph:SetPosition(pickinfo.position) --Bullet mark decal local mtl local scale = 0.1 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/bulletmark.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) table.remove(self.bullets,n) bullet.sprite:Release() if enemy~=nil then if enemy.script.health>0 then enemy.script:Hurt(self.bulletdamage,self.player) --kills counter --if enemy.script.health <=0 then -- self.player.kills = self.player.kills + 1 -- end 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)],30) 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 dir = bullet.velocity:Normalize() local force = dir * self.bulletforce * math.max(0,-pickinfo.normal:Dot(dir)) --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 else bullet.position = bullet.position+travel bullet.sprite:SetPosition(bullet.position - bullet.velocity:Normalize()*1) if bullet.sprite:Hidden() then dist = (bullet.position-bullet.origin):Length() if dist>bullet.sprite:GetSize().y then bullet.sprite:Show() end end end end firstbullet = false end end function Script:Fire() if self.player.weaponlowerangle==0 then local currenttime=Time:GetCurrent() if self.lastfiretime==nil then self.lastfiretime=0 end if currenttime-self.lastfiretime>self.refirerate then if self.currentaction==nil then self.lastfiretime = currenttime if self.clipammo==0 then if self.sound.dryfire then if self.suspenddryfire~=true then self.sound.dryfire:Play() end end else self.currentaction="fire" if #self.sound.fire>0 then self.sound.fire[math.random(#self.sound.fire)]:Play() end self.clipammo = self.clipammo - 1 self.firetime = Time:GetCurrent() self.muzzlelight:Point(self.player.camera,1) self.muzzlelight:Show() self.muzzleflash:SetAngle(math.random(0,360)) --self.animationmanager:SetAnimationSequence("Fire",self.firespeed,300,1,self,self.EndFire) self.entity:PlayAnimation("Fire",self.firespeed,300,1,"EndFire") --Spawn bullet local n for n=1,self.pellets do local d = Transform:Normal(0,0,1,self.player.camera,nil) d = d + Vec3(math.random(-1,1),math.random(-1,1),math.random(-1,1)) * self.scatter d = d:Normalize() local p if self.muzzle then p=self.muzzle:GetPosition(true) self:SpawnBullet(p,d*self.bulletspeed) else System:Print("Warning: Muzzle entity not found.") end end end else self.cancelreload=true end end end end --Creates a bullet function Script:SpawnBullet(position,velocity) local bullet = {} bullet.sprite = tolua.cast(self.tracer:Instance(),"Sprite") bullet.sprite:SetPosition(position) bullet.sprite:AlignToVector(velocity) bullet.sprite:Hide() bullet.position = position bullet.origin = Vec3(position.x,position.y,position.z) bullet.velocity = velocity table.insert(self.bullets,bullet) 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*Time:GetSpeed() end if self.landoffset<0 then jumpbob = jumpbob + (Math:Sin(self.landoffset))*0.01 self.landoffset = self.landoffset + 10*Time:GetSpeed() 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:SetRotation(self.rotation) self.entity:SetPosition(sway*self.entity.scale.x,bob+jumpbob,0) self.entity:Translate(self.offset,false) --self.animationmanager:Update() end function Script:Release() if self.emitter~=nil then self.emitter[0]:Release() self.emitter[1]:Release() self.emitter[2]:Release() self.emitter=nil end if self.sound~=nil then ReleaseTableObjects(self.sound) self.sound=nil end end function Script:Cleanup() self.tracer:Release() end
  2. This one works for me. You might need to post your whole script with your question isn't working so they can look through it for the error: Script.ammoamount = 6 --float "Ammo Amount Per" Script.ammotype= 2 --int "Ammo Type" Script.maxammo="" --int "Max Ammo" Script.ammo = 5 Script.removeBodyTime = 20 --int "Despawn Time" Script.removeBodyTimer = 0 Script.useOnce = true --bool "Use Once" Script.enabled = true --bool "Enabled" Script.floatup1 = false Script.counter= 0 function Script:Start() --Load a sound self.sound = Sound:Load("Sound/Interaction/pickupammo.wav") self.enabled = true self.entity:SetMass(0) local os = self.entity:GetPosition() self.entity:SetPosition(os.x,os.y+1,os.z) end function Script:floatUp(amount) local a1 = self.entity:GetPosition() local b1 = amount/20 self.entity:SetPosition(a1.x,a1.y + b1,a1.z) end function Script:UpdatePhysics() local window = Window:GetCurrent() if window:KeyHit(Key.O) then self:ChangeFloat() end local lastpos = self.entity:GetPosition() if self.enabled==true then if self.lastchangetime==nil then self.lastchangetime=0 end local t = Time:GetCurrent() local floatamount if self.floatup1==true then floatamount= 0.03 else floatamount = -0.03 end self:floatUp(floatamount) self.counter = self.counter +1 if self.counter >= 100 then self:ChangeFloat() self.counter=0 end self.lastchangetime = t end end function Script:ChangeFloat() if (self.floatup1 == false) then self.floatup1=true else self.floatup1=false end end function Script:UpdateWorld() self.entity:Turn(0,Time:GetSpeed(),0,true) self.removeBodyTimer = self.removeBodyTimer + (Time:GetSpeed()/100) if (self.removeBodyTimer > self.removeBodyTime) then self:IsHidden() end end function Script:Collision(entity, position, normal, speed) if entity:GetKeyValue("type")=="player" then for a = 0, 10 do if entity.script.weapons[a]~=nil then if entity.script.weapons[a].index == self.ammotype then if entity.script.weapons[a].ammo + entity.script.weapons[a].clipammo < entity.script.weapons[a].maxammo then entity.script.weapons[a].ammo = entity.script.weapons[a].ammo + self.ammoamount --Make sure the sound exists and play it if self.sound then self.sound:Play() end if entity.script.weapons[a].ammo + entity.script.weapons[a].clipammo > entity.script.weapons[a].maxammo then entity.script.weapons[a].ammo = entity.script.weapons[a].maxammo - entity.script.weapons[a].clipammo end if self.useOnce then self:IsHidden() end end end end end end end function Script:IsHidden() self.entity:Hide() if self.entity:Hide() then self.entity:Release() end end
  3. Possibly you need to change every "rotateC" to "self.rotateC" ?
  4. Shadmar made a shader for metals in the workshop that might work. He used substance painter, too, I believe. https://steamcommunity.com/sharedfiles/filedetails/?id=658772226&searchtext=
  5. Thanks for the help, man. I'll probably not do the onAttacked thing. I can't get it to work and that was just like an extra thing anyway. I'm definitely going to study this though and see if I can make it do more stuff. I just need to keep improving my understanding of the thinking behind it. Peace.
  6. Ok so if I do it like this I can get the others to attack, so it appears that the player is somewhere connected to this script. I just removed the "if" statement and told it to set mode to attack: function Script:onAttacked(data) System:Print("Yeah it's calling this function") self.target = data.player self:SetMode("attack") end Here on the raise event we're calling the self.entity:GetPosition as the crawler who is being shot, right? RaiseEvent("onAttacked", { hurtMonsterPosition = self.entity:GetPosition(), player = distributorOfPain}) ...and later in the "if" statement "data.hurtMonsterPosition" is itself from above. So we're telling it to get the distance from itself to itself? if data.hurtMonsterPosition:GetDistance(self.entity:GetPosition(),false) < 1000 then
  7. Ok. Yeah, that works. It does the System:Print(). But it still doesn't appear to be alerting the other crawlers next to it. It seems to have also solved that issue with getting an error when the crawler is beyond the pick range for health. I appreciate your help with this, man. I wish I could be more useful but this is all new to me. It's probably something on my end at this point but I don't even know where to look. I noticed in the onDead event I had to write "self.kills = self.kills +1" in the enemyDied(data) function, but also you put " subId = subId + 1" in the SubscribeEvent(eventName, script, func). Does it need something like that again? My best guess is its in the function itself? This is the function currently. Maybe it's one of these true/false things? or I changed the distance to 500 just for testing but don't know if that would do anything. function Script:onAttacked(data) System:Print("Yeah it's calling this function") -- I don't recall if this is the correct syntax for distance checks but it gets the idea across. you'll have to research distance checks. if data.hurtMonsterPosition:GetDistance(self.entity:GetPosition(true),false) < 500 then -- if this monster is in a given range of the monster that was attacked then assign this monster the player target as well and it'll come running towards it! self.target = data.player end end
  8. I figured out that if I raise the event under within the health > 0 statement I don't get that error, but it still doesn't reach the onAttacked function, as the System:Print() doesn't do anything. if self.health>0 then if self.target==nil then RaiseEvent("onAttacked", { hurtMonsterPosition = self.entity:GetPosition(), player = distributorOfPain}) self.target=distributorOfPain self:SetMode("attack") end Having it like this seemed to let things run smoothly and then for no reason eventually I would get that error. But that appears to be only when I shoot an enemy from so far away that the pick isn't grabbing their name (and health). Since I put the enemy name in the onDead loop maybe that's giving me that error?
  9. Sure. Here you go: import "Scripts/Functions/GetEntityNeighbors.lua" --Public values Script.name = "" Script.despawnTime = 60 --int "Despawn Time" Script.despawnTimer = 0 Script.removeBodyTime = 8 Script.removeBodyTimer = 0 Script.maxhealth=40 --int "Max Health" 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" Script.attackdelay=300--int "Attack delay" Script.animspeedrun=0.03--float "Run anim speed" Script.animspeedDeath= 0.028 --float "Death anim Speed" Script.speed= 5 --float "Move Speed" --Private values Script.damage=20 + math.random(-10,10) Script.attackrange=1.7 Script.updatefrequency=500 Script.lastupdatetime=0 Script.prevtarget=nil Script.followingtarget=false Script.maxaccel=15 Script.lastupdatetargettime=0 Script.attackmode=1 Script.attackbegan=0 Script.attack1sound=""--path "Attack 1 sound" "Wav file (*.wav):wav|Sound" Script.attack2sound=""--path "Attack 2 sound" "Wav file (*.wav):wav|Sound" Script.alertsound=""--path "Alert sound" "Wav file (*.wav):wav|Sound" Script.deathsound=""--path "Death sound" "Wav file (*.wav):wav|Sound" Script.idlesound=""--path "Idle sound" "Wav file (*.wav):wav|Sound" Script.headshotDmg = 7 --headshot multiplier 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) 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 if d < self.sightradius then --added so they don't charge from any distance return entity.script 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 Script:Start() self.entity:SetKeyValue("type","enemy") self.despawnTimer = 0 --Handle default parameters if speed==nil then speed=5.0 end if blendtime==nil then blendtime=500 end if mode==nil then mode=0 end if self.entity:GetMass()==0 then self.entity:SetMass(10) end self.entity:SetPickMode(Entity.BoxPick,true) self.entity:SetPickMode(1,false) self.entity:SetPhysicsMode(Entity.CharacterPhysics) self.entity:SetCollisionType(Collision.Prop,true) self.entity:SetCollisionType(Collision.Character,false) if self.enabled then if self.target~=nil then self:SetMode("roam") else self:SetMode("idle") end end self.sound={} if self.alertsound then self.sound.alert = Sound:Load(self.alertsound) end self.sound.attack={} if self.attack1sound then self.sound.attack[1] = Sound:Load(self.attack1sound) end if self.attack2sound then self.sound.attack[2] = Sound:Load(self.attack2sound) end if self.idlesound then self.sound.idle = Sound:Load(self.idlesound) end self.lastidlesoundtime=Time:GetCurrent()+math.random(1,20000) --Headshot Box self.headshotbox = self.entity:FindChild("Head") -- or whatever you name the head limb in the model tree if self.headshotbox ~= nil then self.headshotbox.script.parent = self.entity self.headshotbox.script.health = self.health self.headshotbox.script.damageMulti = self.headshotDmg end self.onAttackedId = SubscribeEvent("onAttacked", self, self.onAttacked) end function Script:CleanUp() -- (Rick) Unsubscribe(self.onAttackedId) end function Script:Hurt(damage,distributorOfPain) RaiseEvent("onAttacked", { hurtMonsterPosition = self.entity:GetPosition(), player = distributorOfPain}) if self.health>0 then if self.target==nil then self.target=distributorOfPain self:SetMode("attack") end self.health = self.health - (damage + math.random(-4,4)) --local entity = Prefab:Load("Damage numbers/Damage number.pfb") --entity:SetPosition(self.entity:GetPosition(true)+Vec3(0,2,0)) --entity.script:CreateDamageNumber(damage + math.random(-1,3),0.7,size,color,Vec3(0,0.02,0)) if self.health<=0 then self.headshotbox.script.health = 0 self.entity:SetMass(0) self.entity:SetCollisionType(0) self.entity:SetPhysicsMode(Entity.RigidBodyPhysics) self:SetMode("dying") self:DropLoot() RaiseEvent("onDead", { enemyName = self.name.." was killed by player" }) --(Rick) end end end -- if this is the function linked to the onAttacked event function Script:onAttacked(data) System:Print("Yeah it's calling this function") -- I don't recall if this is the correct syntax for distance checks but it gets the idea across. you'll have to research distance checks. --if data.hurtMonsterPosition:GetDistance(self.entity:GetPosition(),true) < 500 then -- if this monster is in a given range of the monster that was attacked then assign this monster the player target as well and it'll come running towards it! self.target = data.player -- 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:GetCharacterControllerAngle() + 180.0 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.entity:PlayAnimation("Idle",0.01) self.entity:Stop()--stop following anything elseif mode=="roam" then if self.target~=nil then self.entity:PlayAnimation("Run",self.animspeedrun) 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 if self.sound.alert then self.entity:EmitSound(self.sound.alert) end end self.followingtarget=true self.entity:PlayAnimation("Run",self.animspeedrun,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.entity:PlayAnimation("Death",self.animspeedDeath,300,1,"EndDeath") elseif mode=="dead" then if self.mode == "dead" then self.entity:SetCollisionType(0) self.entity:SetShape(nil) self.entity:SetPhysicsMode(Entity.RigidBodyPhysics) self.enabled=false end end end end function Script:EndAttack() if self.mode=="attack" then if self.target==nil then self:SetMode("idle") return end if self.target.health<=0 then self:SetMode("idle") return end local d = self:DistanceToTarget() if d>self.attackrange then self:SetMode("chase") return end self.entity:Stop() self.attackmode = 1-self.attackmode--switch between right and left attack modes self.entity:PlayAnimation("Attack"..tostring(1+self.attackmode),0.07,500,1,"EndAttack") self.attackbegan = Time:GetCurrent() if self.sound.attack[self.attackmode+1] then if math.random()>0.75 then self.entity:EmitSound(self.sound.attack[self.attackmode+1]) end 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.sound.idle then if t-self.lastidlesoundtime>0 then self.lastidlesoundtime=t+20000*Math:Random(0.75,1.25) self.entity:EmitSound(self.sound.idle,20) end end 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>self.attackdelay then if self.target.entity:GetDistance(self.entity)<1.5 then self.attackbegan=nil self.target:Hurt(self.damage) end 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 if self.entity:GetCharacterControllerAngle()>90.0 then self.entity:AlignToVector(-dx,0,-dz) else self.entity:AlignToVector(dx,0,dz) end end end function Script:UpdateWorld() if self.enabled == true then self.despawnTimer = self.despawnTimer + Time:GetSpeed()/100 if self.despawnTimer > self.despawnTime then self.mode = "dead" self.entity:Hide() self.script = nil end end if self.mode == "dead" then self.removeBodyTimer = self.removeBodyTimer + (Time:GetSpeed()/100) if (self.removeBodyTimer > self.removeBodyTime) then self.entity:Hide() if self.entity:Hide() then self.entity:Release() self.script = nil end end end end function Script:DropLoot() self.inventory = {} self.inventory[1] = "HUD Elements/Inventory/Prefabs/Health.pfb" self.inventory[2] = "HUD Elements/Inventory/Prefabs/Stamina.pfb" self.inventory[3] = "HUD Elements/Inventory/Prefabs/Shield.pfb" self.inventory[4] = "HUD Elements/Inventory/Prefabs/Health.pfb" self.inventory[5] = "HUD Elements/Inventory/Prefabs/Stamina.pfb" self.inventory[6] = "HUD Elements/Inventory/Prefabs/Shield.pfb" self.gun = {} self.gun[1] = "AddOns/FPS Weapons Pack/pickup mp5.pfb" self.gun[2] = "AddOns/FPS Weapons Pack/pickup pistol.pfb" self.gun[3] = "AddOns/FPS Weapons Pack/pickup shotgun.pfb" self.gun[4] = "AddOns/FPS Weapons Pack/pickup m4.pfb" self.gun[5] = "AddOns/FPS Weapons Pack/pickup machete.pfb" self.ammo = {} self.ammo[1] = "Prefabs/Ammo Prefabs/9 ammo Hover.pfb" self.ammo[2] = "Prefabs/Ammo Prefabs/Combat Rifle Hover (5).pfb" self.ammo[3] = "Prefabs/Ammo Prefabs/mp5 ammo Hover (4).pfb" self.ammo[4] = "Prefabs/Ammo Prefabs/Shotgun Shells Hover(3).pfb" math.randomseed(Time:Millisecs()) num = math.random(1, 100) if num >= 0 and num < 15 then local spawn = Prefab:Load(self.inventory[math.random(1,6)]) local SpawnPos = self.entity:GetPosition() + Vec3(0,1.5,0) spawn:SetPosition(SpawnPos) return elseif num >= 15 and num <= 20 then local spawn = Prefab:Load(self.gun[math.random(1,5)]) local SpawnPos = self.entity:GetPosition() + Vec3(0,1.5,0) spawn:SetPosition(SpawnPos) return elseif num > 20 and num <= 40 then local spawn = Prefab:Load(self.ammo[math.random(1,4)]) local SpawnPos = self.entity:GetPosition() + Vec3(0,1.5,0) spawn:SetPosition(SpawnPos) return end end
  10. Yeah it's not even getting that far. I keep getting the same error.
  11. Oh yeah. That's weird. Because it's written correctly in the code. This is all the code I added. It's all in the crawler script: function Script:Start() ... self.onAttackedId = SubscribeEvent("onAttacked", self, self.onAttacked) --subscribed to event end function Script:CleanUp() -- (Rick) Unsubscribe(self.onAttackedId) --unsubscribed to event end function Script:Hurt(damage,distributorOfPain) if self.health>0 then player = self.target RaiseEvent("onAttacked", { hurtMonsterPosition = self.entity:GetPosition(true), player = distributorOfPain }) --- raise event ... -- if this is the function linked to the onAttacked event function Script:onAttacked(data) --raise event function -- I don't recall if this is the correct syntax for distance checks but it gets the idea across. you'll have to research distance checks. if data.hurtMonsterPosition:GetDistance(self.entity:GetPosition(),false) < 5 then -- if this monster is in a given range of the monster that was attacked then assign this monster the player target as well and it'll come running towards it! self.target = data.player end end In the original kills thing you you showed me you wrote this: function Script:Start() self.onDeadId = SubscribeEvent("onDead", self, self.enemyDied) ...I was trying to figure out where you got "self.onDeadId" I just tried to mimic that in the crawler script. I also tried setting "player = self.target" How would it know what "player" means in the Hurt()? I'm getting there slowly.
  12. I'm getting "attempt to index a nil value" on this line in the event system script: local scriptFunc = events[eventName].scriptFunction I had added these to the crawler script: function Script:Start() self.onAttackedId = SubscribeEvent("onAttacked", self, self.onAttacked) ... function Script:CleanUp() -- (Rick) Unsubscribe(self.onAttackedId) end Just tried to mimic what you did before.
  13. Ah ok. Hold on let me see if I can figure that out.
  14. That one doesn't seem to be doing anything. I have it set up in the crawler script like: function Script:Hurt(damage,DistributorofPain) RaiseEvent("onAttacked", { hurtMonsterPosition = self.entity:GetPosition(true), player = distributorOfPain }) -- the script doesn't reference "player" anywhere else. Is it that? -- if this is the function linked to the onAttacked event function Script:onAttacked(data) -- I don't recall if this is the correct syntax for distance checks but it gets the idea across. you'll have to research distance checks. if data.hurtMonsterPosition:GetDistance(self.entity:GetPosition(),true) < 500 then -- if this monster is in a given range of the monster that was attacked then assign this monster the player target as well and it'll come running towards it! self.target = data.player end end
  15. This is cool, man. It's totally working. In the crawler script I set it like this: RaiseEvent("onDead", { enemyName = self.name.." was killed by player" }) and in the player script under enemyDied(data) like you said: self.killMessage = data.enemyName What's another event that this would be good for? I want to try and see if I can follow the pattern and piece one together myself. I'm going to also see if I can get the names to list downward with a table iteration. That ought to keep me going for awhile.
×
×
  • Create New...