View unanswered posts | View active topics It is currently Wed Dec 25, 2024 5:37 am



Reply to topic  [ 6 posts ] 
 Unknown issue in my first lua script. 
Author Message
User avatar

Joined: Sun Sep 17, 2017 11:17 pm
Posts: 35
Reply with quote
Post Unknown issue in my first lua script.
I am trying to make a script for a charge-up healing burst for an actor, (hold down a button, meter fills up, heals everyone around him when it's full), but it refuses to work after several hours of tweaking.

The console keeps giving me this:
ERROR: Dummy.rte/Actors/Dummy/ChargeHeal.lua:21: attempt to index global 'self' (a nil value)

(I'm testing the script on a dummy)

Here is the script:
Code:
function Create(self)
   self.ChargeTimer = Timer()
   self.Key = 3
   self.AI = NativeHumanAI:Create(self)
end

function Update(self)

   if self:IsPlayerControlled() and UInputMan:KeyHeld(self.Key) then
      self.Meter = CreateAEmitter("Meter")
      self.Meter.Pos = self.MovableMan.AboveHUDPos + Vector(0,27)
      if math.ceil(self.ChargeTimer.ElapsedSimTimeMS/500) < 16 then
         self.Meter.Frame = math.ceil(self.ChargeTimer.ElapsedSimTimeMS/500)
      else
         self.Meter.Frame = 16
      end
      MovableMan:AddParticle(self.Meter)
      end

   end
      if self:IsPlayerControlled() and UInputMan:KeyReleased(self.Key) and self.ChargeTimer:IsPastSimMS(7500) then
      for actor in MovableMan.Actors do
         local avgx = actor.Pos.X - self.Pos.X;
         local avgy = actor.Pos.Y - self.Pos.Y;
         local curdist = 200;
         local dist = math.sqrt(avgx ^ 2 + avgy ^ 2);
         if dist < curdist and actor.ClassName == "AHuman" then
            actor.Health = 100;
            actor:FlashWhite(250);
      end
   end
end

function UpdateAI(self)
   self.AI:Update(self)
end


If anyone can help me figure this out, I'd be more than grateful :oops:


Wed Dec 06, 2017 8:48 pm
Profile
User avatar

Joined: Tue Jun 12, 2007 11:52 pm
Posts: 13144
Location: Here
Reply with quote
Post Re: Unknown issue in my first lua script.
It looks like you have a misplaced 'end'.

This is what your code looks like when properly indented, with the current 'end' placement -

Code:
function Create(self)
   self.ChargeTimer = Timer()
   self.Key = 3
   self.AI = NativeHumanAI:Create(self)
end

function Update(self)

   if self:IsPlayerControlled() and UInputMan:KeyHeld(self.Key) then
      self.Meter = CreateAEmitter("Meter")
      self.Meter.Pos = self.MovableMan.AboveHUDPos + Vector(0,27)

      if math.ceil(self.ChargeTimer.ElapsedSimTimeMS/500) < 16 then
         self.Meter.Frame = math.ceil(self.ChargeTimer.ElapsedSimTimeMS/500)
      else
         self.Meter.Frame = 16
      end

      MovableMan:AddParticle(self.Meter)
   end

end <--------- misplaced

if self:IsPlayerControlled() and UInputMan:KeyReleased(self.Key) and self.ChargeTimer:IsPastSimMS(7500) then
   for actor in MovableMan.Actors do
      local avgx = actor.Pos.X - self.Pos.X;
      local avgy = actor.Pos.Y - self.Pos.Y;
      local curdist = 200;
      local dist = math.sqrt(avgx ^ 2 + avgy ^ 2);
      if dist < curdist and actor.ClassName == "AHuman" then
         actor.Health = 100;
         actor:FlashWhite(250);
      end
   end
end

function UpdateAI(self)
   self.AI:Update(self)
end


The second "self:IsPlayerControlled()" block is outside of the Update(self) block.

Move the end and properly indented:

Code:
function Create(self)
   self.ChargeTimer = Timer()
   self.Key = 3
   self.AI = NativeHumanAI:Create(self)
end

function Update(self)

   if self:IsPlayerControlled() and UInputMan:KeyHeld(self.Key) then
      self.Meter = CreateAEmitter("Meter")
      self.Meter.Pos = self.MovableMan.AboveHUDPos + Vector(0,27)

      if math.ceil(self.ChargeTimer.ElapsedSimTimeMS/500) < 16 then
         self.Meter.Frame = math.ceil(self.ChargeTimer.ElapsedSimTimeMS/500)
      else
         self.Meter.Frame = 16
      end

      MovableMan:AddParticle(self.Meter)
   end

   if self:IsPlayerControlled() and UInputMan:KeyReleased(self.Key) and self.ChargeTimer:IsPastSimMS(7500) then
      for actor in MovableMan.Actors do
         local avgx = actor.Pos.X - self.Pos.X;
         local avgy = actor.Pos.Y - self.Pos.Y;
         local curdist = 200;
         local dist = math.sqrt(avgx ^ 2 + avgy ^ 2);
         if dist < curdist and actor.ClassName == "AHuman" then
            actor.Health = 100;
            actor:FlashWhite(250);
         end
      end
   end

end

function UpdateAI(self)
   self.AI:Update(self)
end


Wed Dec 06, 2017 10:11 pm
Profile
User avatar

Joined: Sun Sep 17, 2017 11:17 pm
Posts: 35
Reply with quote
Post Re: Unknown issue in my first lua script.
It works! But it's also discovered a new issue, the script is completely ignoring the stuff I put about the charge meter, and instead triggering the heal burst the second I press C. Any idea how I can fix this?

PS, thanks a ton for your help <3


Wed Dec 06, 2017 10:24 pm
Profile

Joined: Fri Sep 10, 2010 1:48 am
Posts: 666
Location: Halifax, Canada
Reply with quote
Post Re: Unknown issue in my first lua script.
You're never resetting your charge timer - timers start counting from the instant they're created and keep going up til they're reset. You need to make it reset when the key isn't held (just put an else on the line about the key being held).

Also, your shortest distance could be better accomplished with SceneMan:ShortestDistance(self.Pos, actor.Pos, true), which'll give you the vector distance between them, and doing .Magnitude on it to get that as a single number. I'd also suggest making curdist a self variable (probably with a different name) and putting it in the create function, so you don't make it for every actor in MovableMan.Actors every time update runs (if you can not do things when you're in big loops like this, you should), plus it makes it easier to find and change later.

If it doesn't work after this, it'd probably be a good idea to change how it works a bit, you could streamline things a lot by using the meter's frame as a counter: store the current frame as a self variable, have the timer just increment the frame every x MS when the key is being held then reset the timer, and have the healing occur once the stored frame reaches its max value, then reset the frame to the min value. Basically, trying to use 1 timer for everything and do math with its elapsed time probably makes the logic more difficult than it needs to be.


Wed Dec 06, 2017 11:00 pm
Profile
User avatar

Joined: Sun Sep 17, 2017 11:17 pm
Posts: 35
Reply with quote
Post Re: Unknown issue in my first lua script.
Bad Boy wrote:
You're never resetting your charge timer - timers start counting from the instant they're created and keep going up til they're reset. You need to make it reset when the key isn't held (just put an else on the line about the key being held).

Also, your shortest distance could be better accomplished with SceneMan:ShortestDistance(self.Pos, actor.Pos, true), which'll give you the vector distance between them, and doing .Magnitude on it to get that as a single number. I'd also suggest making curdist a self variable (probably with a different name) and putting it in the create function, so you don't make it for every actor in MovableMan.Actors every time update runs (if you can not do things when you're in big loops like this, you should), plus it makes it easier to find and change later.

If it doesn't work after this, it'd probably be a good idea to change how it works a bit, you could streamline things a lot by using the meter's frame as a counter: store the current frame as a self variable, have the timer just increment the frame every x MS when the key is being held then reset the timer, and have the healing occur once the stored frame reaches its max value, then reset the frame to the min value. Basically, trying to use 1 timer for everything and do math with its elapsed time probably makes the logic more difficult than it needs to be.

Very helpful, thank you. I've been self teaching lua for a while now just by looking through existing scripts, still very new to most of it. I'll try and do what you suggested, and give you an update if I have any more difficulty.


Wed Dec 06, 2017 11:21 pm
Profile

Joined: Fri Sep 10, 2010 1:48 am
Posts: 666
Location: Halifax, Canada
Reply with quote
Post Re: Unknown issue in my first lua script.
Hey, that's how I did it and it worked out well.
I'd also suggest looking at weegee's missionmaking tutorials (particularly the first 3 or 4) - some of the stuff, especially in the later ones, is pretty specific to activities but they can still be useful as a basic way of learning. And, if you want more structured, general stuff, pil (programming in lua) is probably useful, though I've never read through it all. Also, the drl wiki lua stuff is an absolute godsend, though keep in mind that some things in it are wrong or not well explained.

And yeah, if you have questions or want another pair of eyes on your script, just pop back in of course.


Thu Dec 07, 2017 4:39 am
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 6 posts ] 

Who is online

Users browsing this forum: No registered users


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by STSoftware for PTF.
[ Time : 0.030s | 13 Queries | GZIP : Off ]