Data Realms Fan Forums
http://45.55.195.193/

AEmitter Self-Damage
http://45.55.195.193/viewtopic.php?f=1&t=29690
Page 1 of 1

Author:  Mongoska [ Thu Jan 26, 2012 1:10 am ]
Post subject:  AEmitter Self-Damage

Hullo!!!
I'm trying to make my AEmitter's particles do damage to anything except the actor that has it attached via script.
Essentially the actor has the AEmitter, which appears whenever it fires, offset from its leg. This means if it fires it while, say, falling, it is in danger of obliterating itself from the inside out (since legs are so floppy). Since it's a melee attack, this is highly undesirable and the particles need to within close range of the actor (it wouldn't work if I offset the emitter so far that it couldn't touch the actor).

Is this fixable? Sorry if it's something glaringly obvious - I'm not entirely competent at this scripting language yet!

Author:  Asklar [ Thu Jan 26, 2012 3:32 am ]
Post subject:  Re: AEmitter Self-Damage

Hmm...

You could use SetWhichMONotToHit(Actor.ID,-1), which would make the particles not hit the actor. The problem is that lua is kinda slow, so there is a chance that the particles will hit the actor before that line executes.

Author:  Mongoska [ Thu Jan 26, 2012 4:06 am ]
Post subject:  Re: AEmitter Self-Damage

Righto!
Lua is new to me (since yesterday), but I had a go at implementing that code...

Code:
function Create(self)
   self.MOPixel:SetWhichMONotToHit(Actor.ID,-1)
end


That didn't work, so I tried this...

Code:
function Create(self)
   self.MOPixel:SetWhichMONotToHit(Actor.ClassName("Maximilian"),-1)
end


...Which didn't work either. If you please, could you tell me if I am doing it wrong? Should I be applying the script to the AEmitter instead of directly to the MOPixel? Is my lua complete nonsense?
Oh, also, if you wouldn't mind, what is that "-1" for?

Author:  CaveCricket48 [ Thu Jan 26, 2012 4:31 am ]
Post subject:  Re: AEmitter Self-Damage

The "-1" is used to tell the function how long it should ignore the MO, "-1" being indefinitely.

Now, from what I gather, I assume this script is attached to the emitter, yes?

I would recommend that instead of spawning an emitter to spawn particles to do damage, that you throw out the emitter completely and have a script on the actor that spawns the damage particles.

The issue with your current setup is that there isn't an easy way for Lua to grab a pointer to a particle that an emitter fired, so you can't properly apply functions to those particles. Now, if you have a script that spawns the particles directly, you have full access to those particles.

So, a simple script that is attached to an actor and spawns the particle once.
Code:
function Create(self)

-- This defines what particle we're trying to create,
--but doesn't actually spawn it
   self.damagePar = CreateMOPixel("PresetName of particle");

-- Sets the position of the particle over "self," with "self" being our actor
   self.damagePar.Pos = self.Pos;

-- this may look complicated, but it really isn't. What it does
-- is that it sets the velocity of the particle to (30,0) and
-- rotates the vector so it's pointing in the direction that the actor is aiming
   self.damagePar.Vel = Vector(30,0):RadRotate(self:GetAimAngle(true));

-- setting the particle to ignore collisions with our actor
   self.damagePar.Vel:SetWhichMONotToHit(self,-1);

-- this is what actually adds the particle into the simulation.
-- Note how it comes after the code where we modify it, meaning
-- as soon as it spawns it's working as it should
   MovableMan:AddParticle(self.damagePar);

end

Author:  Asklar [ Thu Jan 26, 2012 4:33 am ]
Post subject:  Re: AEmitter Self-Damage

Well, first off, posting this thread in here while it should go in the lua scripting one. =P!

Now, what I posted was just the syntax, not actual code.

So, to begin with, it should be self:SetWhichMOToNotHit instead of self.MOPixel, because self is the MO which has the script attached to.

Now, getting the ID of the actor with this script would make all the process even slower and wouldn't probably work.
What you could do could be giving the actor a script which stores it's ID in a global variable and then use it in here, but that would be too much fooling around for something this simple.

There might be a simpler way, something obvious I'm missing.

Anyway, this is how SetWhichMoToNotHit works.

EDIT:

Bah, Ninja'd.

Author:  Mongoska [ Thu Jan 26, 2012 5:13 am ]
Post subject:  Re: AEmitter Self-Damage

Oof, I'm a bit lost, I'm afraid...
I tried splicing the code I already had, which spawns the particle on firing, into the particle code, resulting in this...

Code:
function Create(self)
   self.damagePar = CreateMOPixel("Maximilian Talon Slash");
   self.damagePar.Pos = self.Pos;
   self.damagePar.Vel = Vector(30,0):RadRotate(self:GetAimAngle(true));
   self.damagePar.Vel:SetWhichMONotToHit(self,-1);
   self.fired = false;
end

function Update(self)
   if self:GetController():IsState(Controller.WEAPON_FIRE) and self.FGLeg:IsAttached() and self.fired == false then
      MovableMan:AddParticle(self.damagePar);
      self.fired = true;
   end
   
   if self:IsPlayerControlled() == false then
      self:GetController():SetState(Controller.BODY_CROUCH, false);
   end
   
   local Ctrl = self:GetController();
   if Ctrl:IsState(Controller.BODY_JUMPSTART) then
   else
      self.AngularVel = self.AngularVel * 0.75;
   end
   
   if not self:GetController():IsState(Controller.WEAPON_FIRE) then
      self.fired = false;
   end
   


Which had the strange effect in game of damaging my head once upon firing and not doing anything else.
Following that failure, I tried the reverse, putting the particle code into my original code, replacing the emitter references with MOPixel ones.

Code:
function Create(self)
   local thisID = ToActor(self).ID
   local MoObj
   local MoObjB
   for i = 1, MovableMan:GetMOIDCount() do
      if (i ~= thisID) and (MovableMan:GetRootMOID(i) == thisID) then
         MoObj = MovableMan:GetMOFromID(i)
         if MoObj.PresetName == "Maximilian Head" then
            self.Head = ToAttachable(MoObj)
            break
         end
      end
   end
   
   self.fired = false;
end

function Update(self)
   if self:GetController():IsState(Controller.WEAPON_FIRE) and self.Head:IsAttached() and self.FGLeg:IsAttached() and self.fired == false then
      local damagePar = CreateMOPixel("Maximilian Talon Slash", "Maximilian.rte")
      damagePar.Vel = self.Vel
     self.damagePar.Vel:SetWhichMONotToHit(self,-1);
      if self.HFlipped then
         damagePar.RotAngle = self.Head.RotAngle + 3.1415
      else
         damagePar.RotAngle = self.Head.RotAngle
      end
   
      damagePar.Pos = self.FGLeg.Pos + self.FGLeg:RotateOffset(Vector(0,-15))
      MovableMan:AddParticle(damagePar)
      self.fired = true;
   end
   if self:IsPlayerControlled() == false then
      self:GetController():SetState(Controller.BODY_CROUCH, false);
   end
   local Ctrl = self:GetController();
   if Ctrl:IsState(Controller.BODY_JUMPSTART) then
   else
      self.AngularVel = self.AngularVel * 0.75;
   end

   if not self:GetController():IsState(Controller.WEAPON_FIRE) then
      self.fired = false;
   end


This had the even less satisfactory result of doing apparently nothing.

Where am I going wrong?

Sorry this topic is in the wrong section now, by the way... I initially wasn't sure if I'd need lua or not.

Edit: Oh, yeah, the script was attached to the actor, not the AEmitter.

Author:  Asklar [ Thu Jan 26, 2012 6:31 am ]
Post subject:  Re: AEmitter Self-Damage

Code:
function Create(self)
   self.damagePar = CreateMOPixel("Maximilian Talon Slash");
   self.damagePar.Pos = self.Pos;
   self.damagePar.Vel = Vector(30,0):RadRotate(self:GetAimAngle(true));
   self.damagePar.Vel:SetWhichMONotToHit(self,-1);
   self.fired = false;
end

function Update(self)
   if self:GetController():IsState(Controller.WEAPON_FIRE) and self.FGLeg:IsAttached() and self.fired == false then
      MovableMan:AddParticle(self.damagePar);
      self.fired = true;
   end
   
   if self:IsPlayerControlled() == false then
      self:GetController():SetState(Controller.BODY_CROUCH, false);
   end
   
   local Ctrl = self:GetController();
   if Ctrl:IsState(Controller.BODY_JUMPSTART) then
   else
      self.AngularVel = self.AngularVel * 0.75;
   end
   
   if not self:GetController():IsState(Controller.WEAPON_FIRE) then
      self.fired = false;
   end
   


Here:
Code:
self.damagePar.Vel:SetWhichMONotToHit(self,-1);


You are doing two mistakes:
The first and most notorious one is that you are using self.damagePar.Vel instead of self.damagePar. It's like if you tried to do the function to the property of the MOPixel instead of the MOPixel.

The other one is that the name of the function is actually SetWhichMOToNotHit().

So, it should look like

Code:
self.damagePar:SetWhichMOToNotHit(self,-1)


Fixing that the code should work.

Author:  Mongoska [ Thu Jan 26, 2012 8:26 pm ]
Post subject:  Re: AEmitter Self-Damage

Ah, thanks, guys! I smashed it all together and now it does just ask I required (though there is a little bit more that needs changing in the Lua relating to the particle count, I'll use the Lua subforum).

Attachments:
TalonSlash.lua [1.87 KiB]
Downloaded 203 times

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