[SOLVED]Vector gets zeroed by MrRobot

Discussions about Coding and Scripting
User avatar
PrinceOfFunky
Godlike
Posts: 1160
Joined: Mon Aug 31, 2015 10:31 pm

[SOLVED]Vector gets zeroed by MrRobot

Post by PrinceOfFunky » Tue Nov 07, 2017 6:36 am

I'm back again with a vector issue this time :)
This is the class, a particle that can hit the level geometry, it is bBounce=True so that HitWall() is called instead of Landed():

Code: Select all

/*
 * Supposed to be done by a community
 */

class Particle extends Effects;

const MinDesiredFPS = 55;
 
var ParticleSystem particleSys;

var vector friction;
const frMagnitude = 0.01; //friction cohefficent (0.01) * friction normal (1).

var vector fixedForce;
var vector bounceDir;
var vector ParticleHitNormal;
var Actor ParticleHitWall;
var int bounceCounter;
var bool bHitEffect;

auto state Init {
	event BeginState() {
		bCollideWorld = true;
		particleSys = ParticleSystem(owner);
		if (particleSys == None)
			destroy();
		
		if (particleSys.localPlayer == None)
			particleSys.FindLocalPlayer();
		if (particleSys.localPlayer == None)
			destroy();
			
		GotoState('Resetting');
	}
}

event FellOutOfWorld() {
	GotoState('Resetting');
}

event Timer() {
	GotoState('Resetting');
}

state Resetting
{
	event BeginState() {
		bHidden = true;
		Setup();
	}

	function Setup() {
		local vector relativeLoc;
		local int i;

		for (i = 0; i < particleSys.MaxSetLocationAttempts; ++i) {
			relativeLoc = particleSys.Location + particleSys.RandRangeVec(particleSys.minSpawnLoc, particleSys.maxSpawnLoc);

			if (SetLocation(relativeLoc))
				if (particleSys.allowNewLoc(self))
					if (!particleSys.bEmitInZone || (particleSys.bEmitInZone && (Region.Zone == particleSys.Region.Zone)))
						if ((particleSys.maxDistFromPlayer == 0) || (VSize(Location - particleSys.localPlayer.Location) <= particleSys.maxDistFromPlayer))
							if (!particleSys.bSpawnInViewport || (particleSys.bSpawnInViewport && (PlayerCanSeeMe())))
								break;
		}
		bHidden = i == particleSys.MaxSetLocationAttempts;
		
		if (bHidden) {
			GotoState('Resetting'); 
		} else {
			//Actual reset.
			fixedForce = particleSys.RandRangeVec(particleSys.minFixedForce, particleSys.maxFixedForce);
			SetCollision(particleSys.bBlockByActors, false, false);
			bounceCounter = 0;
			Velocity *= 0;
			Mass = particleSys.particlesMass;
			Texture = particleSys.particlesTexture;
			setTimer(particleSys.resetInterval, false);
			
			GotoState('StartPhysics');
		}
	}
}

function ApplyForce(vector force) {
	Acceleration += (force / Mass);
}

function ApplyAllForces() {
	local ForceInfo forceInfo;
	
	ApplyForce(friction);
	ApplyForce(/*(Region.Zone.ZoneGravity / particleSys.unrealGravityFix) * Mass*/vect(0,0,-9));
	//ApplyForce(Region.Zone.ZoneVelocity);
	//ApplyForce(fixedForce);
	//foreach AllActors(class'ForceInfo', forceInfo)
	//	ApplyForce(forceInfo.force - forceInfo.Location);
}

function Hit(actor HitStuff, vector HitNormal) {
	local HitEffect hitFX;
	local vector bounceDir;
	
	if (HitStuff.IsA('LevelInfo')) {
		if ((particleSys.maxBounces <= 0) || ((particleSys.maxBounces > 0) && (bounceCounter >= particleSys.maxBounces))) {
			ParticleHitNormal = HitNormal;
			ParticleHitWall = HitStuff;
			if (bHitEffect) {
				hitFX = spawn(particleSys.hitEffectClass,,,Location);
				if (hitFX != None)
					hitFX.init(ParticleHitNormal, ParticleHitWall);
			}
			
			if (!particleSys.bResetOnHit)
				GotoState('Idle');
			else
				GotoState('Resetting');
		} else {
			if (VSize(bounceDir) == 0) {
				/*
				bounceDir = vect(1,1,1);
				if (HitNormal.X != 0)
					bounceDir.X = -1 * particleSys.particlesBuoyancy;
				else if (HitNormal.Y != 0)
					bounceDir.Y = -1 * particleSys.particlesBuoyancy;
				else if (HitNormal.Z != 0)
					bounceDir.Z = -1 * particleSys.particlesBuoyancy;
					
				Log(Acceleration@Velocity@bounceDir);
				ApplyForce(bounceDir);
				*/
				//FIXME
				bounceDir = HitNormal;
				Log(-1@bounceDir);
				
				bounceCounter++;
			}
		}
	} else {
		//FIXME - Handle bouncing on actors without HitNormal.
		if (!particleSys.bResetOnHit)
			GotoState('Idle');
		else
			GotoState('Resetting');
	}
}

event HitWall(vector HitNormal, actor HitWall) {
	Hit(HitWall, HitNormal);
}

state Idle {
Ignores HitWall;
}

state StartPhysics {
	event BeginState() {
		SetPhysics(PHYS_Projectile);
	}

	event EndState() {
		//The particle will move back to the initial position, it needs to be non-collidable.
		SetCollision(false);
		SetPhysics(PHYS_None);
	}

	event Touch(Actor Other) {
		if (Other.bCollideActors && Other.bBlockActors)
			Hit(Other, vect(0,0,0));
	}

	event ZoneChange(ZoneInfo NewZone) {
		particleSys.particleZoneChange(self, NewZone);
	}

	event Tick(float DeltaTime) {
		Log(0@bounceDir);
	
		friction = (Velocity * -1);
		friction = Normal(friction);
		friction *= frMagnitude;
		
		ApplyAllForces();
			
		Log(1@Velocity);
		Velocity += Acceleration;
		Log(2@Velocity);
		//Limiting the Velocity to the Zone Terminal Velocity.
		//Limit positive velocity.
		if (Velocity.X > Region.Zone.ZoneTerminalVelocity)
			Velocity.X = Region.Zone.ZoneTerminalVelocity;
		if (Velocity.Y > Region.Zone.ZoneTerminalVelocity)
			Velocity.Y = Region.Zone.ZoneTerminalVelocity;
		if (Velocity.Z > Region.Zone.ZoneTerminalVelocity)
			Velocity.Z = Region.Zone.ZoneTerminalVelocity;
		//Limit negative velocity.
		if (Velocity.X < (Region.Zone.ZoneTerminalVelocity * -1))
			Velocity.X = Region.Zone.ZoneTerminalVelocity * -1;
		if (Velocity.Y < (Region.Zone.ZoneTerminalVelocity * -1))
			Velocity.Y = Region.Zone.ZoneTerminalVelocity * -1;
		if (Velocity.Z < (Region.Zone.ZoneTerminalVelocity * -1))
			Velocity.Z = Region.Zone.ZoneTerminalVelocity * -1;
		
		//Calculate bounce velocity.
		if (VSize(bounceDir) != 0) {
			Log(3@Velocity);
			if (bounceDir.X != 0)
				Velocity.X *= -1;
			else if (bounceDir.Y != 0)
				Velocity.Y *= -1;
			else if (bounceDir.Z != 0)
				Velocity.Z *= -1;
			Log(4@Velocity);
				
			bounceDir *= 0;
		}
			
		 // Reset acceleration
		Acceleration *= 0;
		
		if (DeltaTime > Level.TimeDilation / MinDesiredFPS && FRand() < 0.1) {
			bHidden = true;

			SetCollision(false);
		}
	}
}

event Destroyed() {
	if (particleSys != None) {
		particleSys.particlesCounter--;
		particleSys.enable('timer');
	}
}

defaultproperties
{
   RemoteRole=ROLE_None
   DrawType=DT_Sprite
   Style=STY_Translucent
   DrawScale=0.2
   Mass=1
   bBounce=True
   CollisionRadius=1
   CollisionHeight=1
}
There are 4 Logs, only care about the Log(-1@...) and Log(0@...), Log#-1 is called in HitWall() and prints the HitNormal, which gets saved in a variable called bounceDir. Log#0 is called in Tick(), from within the state 'StartPhysics' and it prints bounceDir.
bounceDir is multiplied by 0 only inside an "if" body, which is never called cause of the issue I'm gonna talk about.
The issue:

Code: Select all

ScriptLog: -1 -0.000000,-0.000000,1.000000
ScriptLog: 0 0.000000,0.000000,0.000000
As you can see, Log#-1 shows a bounceDir with one dimension set to 1, while Log#0 shows a zeroed bounceDir.
I thought it could have been caused by the "if" body that multiplies bounceDir by 0(even if it is never called), but I commented it out and the issue still occurs.
I know it has to be with something else inside the calss, cause I tried making a very simple class:

Code: Select all

/*
 * Supposed to be done by a community
 */

class Particle extends Effects;

var vector bounceDir;

function Hit(actor HitStuff, vector HitNormal) {
	bounceDir = HitNormal;
	Log(-1@bounceDir);
}

event HitWall(vector HitNormal, actor HitWall) {
	Hit(HitWall, HitNormal);
}

auto state StartPhysics {
	event Tick(float DeltaTime) {
		Log(0@bounceDir);
	}
}

defaultproperties
{
   RemoteRole=ROLE_None
   DrawType=DT_Sprite
   Physics=PHYS_Falling
   bCollideWorld=True
   bBounce=True
}
And the logs are as expected:

Code: Select all

ScriptLog: -1 -0.000000,-0.000000,1.000000
ScriptLog: 0 -0.000000,-0.000000,1.000000
Anyone knows why the vector gets zeroed?
Last edited by PrinceOfFunky on Tue Nov 07, 2017 6:13 pm, edited 1 time in total.
"Your stuff is known to be buggy and unfinished/not properly tested"

nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: Vector gets zeroed by MrRobot

Post by nogardilaref » Tue Nov 07, 2017 1:08 pm

It's because your bounceDir var never gets assigned any value that way in the first place. :)

You have bounceDir declared as a var from the Particle itself at the top, but then you have another bounceDir locally declared in your Hit function.
So when you do bounceDir=... inside Hit, you're not assigning the bounceDir of the class itself, you're only assigning the bounceDir of the local variable.
It's essentially a problem of scoping.

From here, an obvious way to solve it is to use a different name for your local variable (or not use it in the first place, probably declaring it at all was an oversight), and another way is just like you would do in languages like Java (which UScript is based on), by explicitly stating that you want to access/modify the actual class var by using "self": self.bounceDir .

User avatar
PrinceOfFunky
Godlike
Posts: 1160
Joined: Mon Aug 31, 2015 10:31 pm

Re: Vector gets zeroed by MrRobot

Post by PrinceOfFunky » Tue Nov 07, 2017 6:13 pm

nogardilaref wrote:It's because your bounceDir var never gets assigned any value that way in the first place. :)
I left the local declaration?! Oh dang what a shame, I must have been very sleepy yesterday D:
Thank you :D I feel bad for MrRobot whom I gave the fault for this issue lol...
"Your stuff is known to be buggy and unfinished/not properly tested"