Data Realms Fan Forums
http://forums.datarealms.com/

Unknown issue in my first lua script.
http://forums.datarealms.com/viewtopic.php?f=1&t=46228
Page 1 of 1

Author:  gridbull [ Wed Dec 06, 2017 8:48 pm ]
Post subject:  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:

Author:  CaveCricket48 [ Wed Dec 06, 2017 10:11 pm ]
Post subject:  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

Author:  gridbull [ Wed Dec 06, 2017 10:24 pm ]
Post subject:  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

Author:  Bad Boy [ Wed Dec 06, 2017 11:00 pm ]
Post subject:  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.

Author:  gridbull [ Wed Dec 06, 2017 11:21 pm ]
Post subject:  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.

Author:  Bad Boy [ Thu Dec 07, 2017 4:39 am ]
Post subject:  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.

Page 1 of 1 All times are UTC [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/