I'm pretty positive what I want to do isn't possible with ActionScript, but it would be nice to be wrong.
I need to pass a variable reference to a function, and have the function change the value of the variable.
So, simplified and not in completely correct syntax, something like this:
function replaceValue(element:*, newValue:String):void
{
element = newValue;
}
var variableToModify:String = "Hello";
replaceValue(variableToModify, "Goodbye");
trace(variableToModify) // traces value of 'Hello', but want it to trace value of 'Goodbye'
Of course, in the replaceValue function, element is a new reference to fungibleValue (or, rather, a new reference to fungibleValue's value). So, while element gets set to the value of newValue, fungibleValue does not change. That's expected but totally not what I want, in this case.
There's a similar question, for Ruby, here Changing value of ruby variables/references
As the question points out, Ruby has a way to accomplish this. BUT is there any way to do this in ActionScript?
If so, it's going to make something stupid a lot easier for me.
No it's not possible the function will always get the value and not the reference. But if you are able to call replaceValue why not returning the new value from your function :
function replaceValue(element:*, newValue:String):String
{
// .. do your work
return newValue;
}
var variableToModify:String = "Hello";
variableToModify = replaceValue(variableToModify, "Goodbye");
trace(variableToModify)
If you pass an Object or a Class, you can modify one fiels based on his name as :
function replaceValue(base:Object, fieldName:String, newValue:String):void {
// do your work
base[fieldName] = newValue;
}
var o:Object={ variableToModify:"Hello" };
replaceValue(o, "variableToModify", "Goodbye");
trace(o.variableToModify);
Related
I am working on a large Flash project.
I have tried "Goto Declaration" but that doesn't seem help.
Btw I am using FlashDevelop. And Yes I can perfectly compile and build TO 100% working source.
Here is a code sample. I know you can't do much with this but tell how I can work with this.
public function aim_(_arg_1:Vector3D, _arg_2:Vector3D, _arg_3:ProjectileProperties):Vector3D
{
var _local_4:Vector3D;
var _local_5:GameObject;
var _local_6:Vector3D;
var _local_7:Number;
var _local_8:Number;
var _local_9:int;
var _local_10:Boolean;
var _local_11:int;
var _local_12:Boolean;
var _local_13:* = undefined;
var _local_14:int = Parameters.data_.aimMode;
var _local_15:Number = (_arg_3.speed_ / 10000);
var _local_16:Number = ((_local_15 * _arg_3.lifetime_) + ((Parameters.data_.Addone) ? 1 : 0));
var _local_17:Number = 0;
var _local_18:Number = int.MAX_VALUE;
var _local_19:Number = int.MAX_VALUE;
aimAssistTarget = null;
for each (_local_5 in map_.goDict_)
{
if (_local_5.props_.isEnemy_)
{
_local_10 = false;
for each (_local_11 in Parameters.data_.AAException)
{
if (_local_11 == _local_5.props_.type_)
{
_local_10 = true;
break;
};
};
What you're trying to achieve is reverse engineering a decompiled code. With "_local" variables you need to investigate what values they are assigned, in what algorithms do they participate, and here you just need to read this single function in its entirety to be able to discern meaning of those local variables. But, you would also need to understand many of the named parameters to get some of those meanings. For example, _local_11 iterates through some Parameters.data_.AAException list of ints, and is compared with current outside loop iterator's props.type_, therefore "AAException" should mean "AA exemption" and _local_10 provides check result, whether current enemy is exempt from AA (whatever is that AA). And so on.
Same with _arg_X variables, you need to find out what's being passed into a function from wherever it's called, and retrieve the context of those parameters, also taking their type into consideration, like here _arg3 is of type "ProjectileProperties", meaning this function should relate to some projectile which properties affect its outcome somehow. Most likely it's taking two vectors of projectile (or source, this is outside of this code) and target (or speed, same here), and generates another vector of yet unknown purpose.
When you have investigated every function like this, you'll have quite a bunch of pieces to a single puzzle that you can combine by references, discovering all the algorithms that combine the code of whatever app you've decompiled. Then you will be able to do targeted modifications of whatever kind you wanted initially. But yes, it'll be better if you'd have access to actual sources from whoever created this the first time.
In short: Think. Think, think and think.
I used to work on AS2 and make games, and now I wanna learn AS3 and have all its nice features (using Flash CS IDE). Now I m trying to rewrite a function to discard it.
function something():void{
//do something
}
function something():void{}
like this. please help or just give some alternatives, thanks.
What you're trying to do is very illogical - a function should be defined once and exist always. Not only that, but it should definitely always behave the same way, especially considering AS3 does not support overloading.
AS3 introduces the OOP paradigm for you to use - this further emphasises the above - you should create classes which define a fixed collection of properties and methods. This way, the intent of each class in your application is clear, and what you expect something to be able to do won't change.
If you absolutely must be able to delete functions, you can assign them to a dynamic object and remove or redefine them with the delete keyword:
var methods:Object = {
something: function():void
{
trace('Still here.');
}
};
methods.something(); // Still here.
delete methods.something;
methods.something(); // TypeError: something is not a function.
methods.something = function():void
{
// Define new function.
}
Or assign an anonymous function to a variable of type Function, from which point you can set the reference to null:
var something:Function = function():void
{
trace("Still here.");
}
something(); // Still here.
something = null;
something(); // TypeError: value is not a function.
something = function():void
{
// Define new function.
}
I want to be able to access a instance on the stage dynamically by looping through an array containing Strings that describes the path.
private var clockKeeper:Array = new Array("LB.anim.clock.lbclock");
trace(stage.LB.anim.clock.lbclock.text);
for (var key in clockKeeper) {
trace(stage[clockKeeper[key]].text);
}
When i access it manually with the first trace statement, it works.
When i do it dynamically it seems like Flash tries to find an object named "LB.anim.clock.lbclock" not LB.anim....
How can i change this behaviour and make it work?
You should try splitting the "path" which should then consist of locally available names, and address each object in order. "Locally available names" means there should be stage.LB, and that object should have a property anim, etc etc.
function getObjectByPath(theRoot:DisplayObjectContainer,
thePath:String,separator:String='.'):DisplayObject
{
var current:DisplayObjectContainer=theRoot;
var splitPath:Array=thePath.split(separator);
while (splitPath.length>0) {
var named:DisplayObject = current.getChildByName(splitPath[0]);
var addressed:DisplayObject=current[splitPath[0]];
// either named or addressed should resolve! Otherwise panic
if (!addressed) addressed=named; else named=addressed;
if (!named) return null; // not found at some position
splitPath.shift();
if (splitPath.length==0) return named; // found, and last
current=named as DisplayObjectContainer;
if (!current) return null; // not a container in the middle of the list
}
// should never reach here, but if anything, just let em
return current;
}
This provides two ways of resolving the path, by name or by property name, and property name takes precedence. You should then typecast the result to proper type.
Yes, call this as follows:
trace((getObjectByPath(stage,clockKeeper[key]) as TextField).text);
Okay so I have a function called changeHandler - it is called by several eventListeners in other functions. I want to write several if statements that evaluate the source of function call and change the dataProvider of my ComboBox depending on the originating function. Example: one of the many functions is called displayCarbs() and has an eventListener like so:
function displayCarbs(event:MouseEvent):void {
myComboBox.addEventListener(Event.CHANGE, changeHandler);
}
(I've removed all of the unnecessary code from the function above)
The if statement inside the changeHandler will look something like this:
if (****referring function = displayCarbs****) {
myComboBox2.dataProvider = new DataProvider(carbItems);
}
I've searched high and low for something that can achieve this, but I just don't have a good enough grasp of AS3 or vocabulary to describe what describe what I mean to get the answer from Google.
The simplest way I can think of... Couldn't you simply create a text string that updates to the name of function before going to changeHandler then in turn changeHandler can check string content and act accordingly..
public var referring_function:String;
function displayCarbs(event:MouseEvent):void
{
referring_function = "displayCarbs";
myComboBox.addEventListener(Event.CHANGE, changeHandler);
}
function displayCarbs(event:Event):void
{
if (referring_function == "displayCarbs")
{ myComboBox2.dataProvider = new DataProvider(carbItems); }
if (referring_function == "displayOthers")
{ myComboBox2.dataProvider = new DataProvider(otherItems); }
// etc etc
}
I cant remember right now if you need == or just = when checking the If statement against strings.
I know there is an accepted answer already, but based on what I gleaned about the problem, here is a solution that wouldn't require adding another variable to check :
function displayCarbs(event:MouseEvent):void
{
myComboBox.addEventListener(Event.CHANGE, changeHandler);
}
function changeHandler(event:Event):void
{
var comboBox:ComboBox = event.target as ComboBox;
if (comboBox.dataProvider == uniqueProvider)
{
myComboBox2.dataProvider = new DataProvider(appropriateItems);
}
}
This should work if the second dataProvider is determined based on the first dataProvider. This of course requires that your uniqueProvider is a class member variable so it has scope within the handler.
I need to create a variable:
var numDots0:Number=0;
But when a button is clicked the variable numDots0 becomes numDots1, then numDots2 on a second click, and so on. I then need to be able to grab that new variable name and use it in a function.
That's a really, really weird request, but anyways:
You can use the key name of an Object to store the property and then change that:
var obj:Object = { numDots0: 0 };
And then when you want to change the name:
delete obj.numDots0;
obj.numDots1 = 1;
Or to easily increment you can use this:
var i:int = 0;
function increase():void
{
delete obj["numDots" + i];
obj["numDots" + (++i)] = i;
}
To access:
trace(obj.numDotsX); // where X is the most recent variable name.
I see absolutely no benefit or need for this, so I strongly suggest taking a look at what you're trying to do and making sure it makes sense and doesn't have a different application.
I am pretty sure you are going the wrong way about the problem you are trying to solve. Dynamic variable names are not something you read in the best practices book.
Anyway to answer your question in AS2 you could use the command eval which would evaluate a string as ActionScript, so you would use something like:
function onClicked(e:MouseEvent):void
{
counter++;
eval("var numDots" + counter +"+:Number=0;");
}
In AS3 that command has been removed (because it leads to bad coding practices - like the things you are trying to do), nevertheless someone implemented an evaluator in AS3:
http://eval.hurlant.com/
With this evaluator add the library to your project and add the following to the snippet above:
function eval(expression:String):void
{
var evaluator:com.hurlant.eval.Evaluator = new com.hurlant.eval.Evaluator();
var bytes:ByteArray = evaluator.eval(expression);
bytes = ByteLoader.wrapInSWF([bytes]);
var context:LoaderContext = null
var loader:Loader = new Loader();
loader.loadBytes(bytes, context);
}
the answer is to not do what you are trying to do and use an array, hash or vector instead. give us a bit more context, or the reason you want to achieve exactly what you want to and why you might believe you'd need a dynamic variable name like that. you shouldn't be using evals or anything that changes variable name at runtime because the gods of programming will strike you down where you stand. i.e., your program is going to break, and when it does, it's going to be harder to debug for sure.
if you are sure this is what you want to do, then i'm wrong, haha. good luck!