Inject AS3 or ABC to a swf file in runtime? - actionscript-3

I've been seeing some tools for a browsergame that injects code to a swf file in order to automate some parts of the game.
I've been reading about swf flash format and I'm still don't knowing how that's possible, maybe the program runs the swf file with a custom flash player?
If you could guide me in this I would be very appreciated, this is very interesting.

Just a try:
var actionString:String = "methodAddOne";
var paramString:String = "1";
function methodAddOne(num:String):void{
trace(Number(num)+1);
}
this[actionString](paramString); //trace: 2
For a queue of params:
var actionString2:String="methodAdd";
var paramString2:String="1,2,3,-6";
function methodAdd(nums:String):void{
var params:Array= nums.split(",");
var out=0;
for each(var num:Number in params){
out += num;
}
trace(out);
}
this[actionString2](paramString2);// returns 0
All calculations, core-Methods,... you have to parse. Very complicated...
E.g. try to parse and calculate "1+2+3-6". Its possible of course, but hard to do with other Stuff and math-grammar.
So, the easier way is to provide a String-based Api with all methods, the
user can predefined use with params.
like this:
var stackString:String = "methodAddOne(100); methodAdd(1,2,3);";
function parseFunctionsString(str:String):void
{
//better use regExp at all the following
var f:String = str.substring(0,str.indexOf("("));
var p:String = str.substring(str.indexOf("(") + 1,str.indexOf(")"));
// clean spaces // also better regExp to validate some other user mistakes - just for this test in this way
f = f.replace(" ","");
p = p.replace(" ","");
//trace("** "+f+" ("+p+")");
if (this[f])
{
this[f](p);
}
else
{
trace("unknown function: "+f);
}
str = str.substr(str.indexOf(";") + 1,str.length - str.indexOf(";") + 1);
if (str.length > 2)
{
parseFunctionsString(str);
}
}
parseFunctionsString(stackString);
// trace:
// 101
// 6
As an idea... Greetings André

Related

ActionSctipt 3.0 Error:

I'm having real trouble trying to access the symbol dynamically, I have 9 buttons that all call this method, and they pass in their location (tl, t, tr, etc.) I've tried this method before on another program and it works without a problem, but in this program it fails.
I am attempting to access a symbol call s_tl (example location), but all I'm getting is undefined (see results).
function turn(btn : String):Function {
return function(e:MouseEvent) {
var players_turn : int;
var chosen : String = "s_" + btn;
trace(this);
trace(this[chosen]);
trace(chosen);
trace(this[chosen]);
// if crosses turn 0 else 1
if (s_c.currentFrame == 1) {
players_turn = 0;
} else {
players_turn = 1;
}
// check who's turn it is if it's been pressed before
if (players_turn == 0 && this[chosen].visible == false) {
this[chosen].gotoAndStop(1);
this[chosen].visible = true;
} else {
this[chosen].gotoAndStop(2);
this[chosen].visible = true;
}
};
}
Results:
[object global]
undefined
s_br
undefined
TypeError: Error #1010: A term is undefined and has no properties.
at MethodInfo-6()
Your problem is the bad code style. You define unnamed unbind function inside function turn() and that's where the root of your problem is. Unbind function exist, as your trace shows, in global addressing context and, unlike function turn(), is not bind to any specific display object. Your buttons probably exist on the same addressing context with turn(). Argument btn is available inside unnamed function because ECMA standard instructs so (if function A creates function B then local variables, including arguments, of A are available as local variables in B), but it is a very very very bad practice that makes code messy and induce headaches.
Please explain what you tried to achieve with that code so we could untangle it and rewrite in not-so-twisted way.
Okey, I basically figured you're doing Tic Tac Toe. Now, guideline. A cell must contain 3 frames: 1st frame for the button graphics, 2nd and 3rd for X and O. Name them your way: s_1, s_2, etc.
for (var i:int = 1; i < 10; i++)
{
var aCell:MovieClip = getChildByName("s_" + i) as MovieClip;
aCell.addEventListener(MouseEvent.CLICK, onTic);
}
function onTic(e:MouseEvent):void
{
var playersTurn:int = s_c.currentFrame;
var aCell:MovieClip = e.currentTarget as MovieClip;
trace(aCell.name);
// Now, the magic.
aCell.gotoAndStop(playersTurn + 1);
aCell.removeEventListener(MouseEvent.CLICK, onTic);
}

Accessing audio via function

In Unityscript I'm able to directly access audio data. In the scene, I have a gameobject with a sound file and a script attached to it.
var mySound : AudioClip;
mySound = audio.clip;
var mySoundChannels = mySound.channels;
However, I'm having problems trying to access audio data via a function:
#pragma strict
var mySound : AudioClip;
function Start()
{
mySound = audio.clip;
GetAudio(mySound);
}
function GetAudio(au)
{
print ("Audio: " + (mySound === au)); // true
//var mySoundChannels = mySound.channels; // works
var mySoundChannels = au.channels; // fails
var stereoOrNot = (mySound.channels == 2 ? "stereo" : " mono"); //works
print(stereoOrNot);
}
I thought I could access au.channels, but I'm not sure where I'm going wrong I (apart from wanting to access audio indirectly)
Since you are using a dynamic variable there, I'm not sure if the var mySoundChannels will be typed to an AudioClip or an int. If it is an AudioClip then it will fail because channels are read only. Try it with int mySoundChannels = au.channels;

Execution order of GS files in a Project

Where can I read documentation concerning the execution order rules for GS files?
To dimension the problem I created two trivial objects, each in their own file.
1_File.gs
var ObjB = new Object();
ObjB.sayName = "[" + ObjA.sayName + "]";
0_File.gs
var ObjA = new Object();
ObjA.sayName = " I'm A ";
A call such as ...
Logger.log(ObjA.sayName + " : " + ObjB.sayName);
... gets the error ...
TypeError: Cannot read property "sayName" from undefined.
If I move the code from 1_File.gs into 0_File.gs, and vice versa, then there is no error and the log shows correctly ...
I'm A : [ I'm A ]
Renaming 0_File.gs to 2_File.gs doesn't affect execution order either, so I assume that order depends on which file gets created first.
Is there no concept of "include" or "import" that would allow me to make order of execution explicit?
Where can I read documentation concerning the execution order rules for GS files?
There is no such documentation and I think will not be any time published. In similar way, an initialization order of the static variables in C++ is also undefined and depends on compiler/linker.
Is there no concept of "include" or "import" that would allow me to make order of execution explicit?
Yes, there is no "includes", "imports" and even "modules", but there are libraries.
Also there is a workaround by using a closure. Bellow is a sample code. By executing the test function the log contains c.d. The idea is to have in all gs files a function started with init. In these functions all global variables are instanced. The anonymous closure is executed during the Code.gs file instancing and calls all "init" functions of all gs files.
Code.gs
var c;
function callAllInits_() {
var keys = Object.keys(this);
for (var i = 0; i < keys.length; i++) {
var funcName = keys[i];
if (funcName.indexOf("init") == 0) {
this[funcName].call(this);
}
}
}
(function() {
callAllInits_();
c = { value : 'c.' + d.value };
})();
function test() {
Logger.log(c.value);
}
d.gs
var d;
function initD() {
d = { value : 'd' };
};
I tackled this problem by creating a class in each file and making sure that each class is instantiated in the original Code.gs (which I renamed to _init.gs). Instantiating each class acts as a form of include and makes sure everything is in place before executing anything.
_init.gs:
// These instances can now be referred to in all other files
var Abc = new _Abc();
var Menu = new _Menu();
var Xyz = new _Xyz();
var Etc = new _Etc();
// We need the global context (this) in order to dynamically add functions to it
Menu.createGlobalFunctions(this);
function onInstall(e) {
onOpen(e);
}
function onOpen(e) {
Menu.build();
}
And classes usually look like this:
menu.gs:
function _Menu() {
this.build = function() {
...
}
...
}
If you have more than one level of inheritance, you need to give the init functions names like init000Foo, init010Bar, and init020Baz, and then sort the init functions by name before executing. This will ensure init000Foo gets evaluated first, then Bar, then Baz.
function callAllInits() {
var keys = Object.keys(this);
var inits = new Array();
for (var i = 0; i < keys.length; i += 1) {
var funcName = keys[i];
if (funcName.indexOf("init") == 0) {
inits.push(funcName);
}
}
inits.sort();
for (var i = 0; i < inits.length; i += 1) {
// To see init order:
// Logger.log("Initializing " + inits[i]);
this[inits[i]].call(this);
}
}
The other answers (i.e., don't write any top-level code which references objects in other files) describe the ideal way to avoid this problem. However, if you've already written a lot of code and rewriting it is not feasible, there is a workaround:
Google App Script appears to load code files in the order they were created. The oldest file first, followed by the next, and the most recently created file last. This is the order displayed in the editor when "Sort files alphabetically" is unchecked.
Thus, if you have the files in this order:
Code.gs
1_File.gs (depends on 0_File.gs)
0_File.gs
An easy fix is to make a copy of 1_File.gs and then delete the original, effectively moving it to the end of the list.
Click the triangle next to 1_File.gs and select "Make a copy"
Code.gs
1_File.gs
0_File.gs
1_File copy.gs
Click the triangle next to 1_File.gs and select "Delete"
Code.gs
0_File.gs
1_File copy.gs
Click the triangle next to 1_File copy.gs and select "Rename", then remove the " copy" from the end.
Code.gs
0_File.gs
1_File.gs
Now 0_File.gs is loaded before 1_File.gs.
This works for me as of December 2021. Quite likely, the other answers are outdated.
You can easily fix this. When you look at the scripts in the "Files" section of the web editor, you see they have an order. Files are evaluated in the order they appear there. Clicking on the three dots to the right of a file name brings up a menu that allows you to move a file up or down.
There is no such order in Google Apps Script. It purely depends on where you have these objects declared and how your function is invoked.
Can you explain a bit about how and when your Logger.log() code will be invoked.
Also, when do you declare your objects objA and objB ?
These will help us provide a better answer
here is how I would do this...
main
function include(filename) {
return ContentService.createTextOutput(filename);
}
function main() {
include('Obj A');
include('Obj B');
Logger.log(ObjA.sayName + " : " + ObjB.sayName);
}
Obj A
var ObjA = new Object();
ObjA.sayName = " I'm A ";
Obj B
var ObjB = new Object();
ObjB.sayName = "[" + ObjA.sayName + "]";

uploading swf file to stencyl issue?

Alright so I am using the stencyl engine to make a flash game, and I wanted to upload an Swf file. The problem is I keep getting an error
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at _247gamesonline_fla::bn0_Symbol1_2/frame1()
Now I went to that part of the fla file that had the error, and tried to see what was wrong, but could not figure it out. Here is the code:
stop();
var doMain:String = this.stage.loaderInfo.url;
var doMainArray:Array = doMain.split("/");
var domainname = doMainArray[2];
var gamename = "nameofgame";
var linktodjp = "http://www.247gamesonline.com/? p=cat&order=2&tag=puzzle&utm_medium=partnergame&utm_campaign=" + gamename + "&utm_source=" + domainname + "&utm_content=partnergame";
var linktodjpfb = "http://www.facebook.com/connect/uiserver.php?app_id=201345053230176&next=http://www.3j.com/processfacebook.php%3Futm_source%3D" + domainname + "%26fgamet%3D76&display=page&cancel_url=http%3A%2F%2Fwww.3j.com%3F3Futm_source%3D" + domainname + "&locale=en_US&return_session=1&session_version=3&fbconnect=1&canvas=0&legacy_return=1&method=permissions.request&perms=publish_stream,offline_access,email,user_birthday,user_interests,read_friendlists";
buttonplay.addEventListener(MouseEvent.CLICK, playlogonow);
logo.addEventListener(MouseEvent.CLICK, gotowebsite);
logo.buttonMode = true;
stop();
function playlogonow(e:Event) {
logo.play();
gotoAndStop(2);
return;
}
function gotowebsite(e:Event) {
navigateToURL(new URLRequest(linktodjp));
return;
}
Also in another part of the code it simply says
on (release) {
_root.play();
}
Help anyone?
Difficult to say by having that code only. Whatever, I would recommend to put many trace statements there to figure out what variable actually equals null and leads to that exception. Then act accordingly.

How to assign URLVariables result to a String Variable?

In the following example (yes, I am coding on my timeline while I try to work this out - I know, I know) I am loading an SWF in an HTML page and then directing the SWF to get the query parameters from the current URL. The query parameter will contain the source for the video to play.
This seems straight forward to me but I cannot get myURL = urlVars.videoloc; to work. More specifically, urlVars.videoloc seems to be undefined rather than holding the query parameter from the URL. All other variables are correct; both wholeURL and urlVars are defined.
//Initialize Global Event Listener
player.addEventListener(Event.ADDED_TO_STAGE, getPlay, false, 0, true);
//Function to play the video
function getPlay(e:Event):void {
var wholeURL:String = ExternalInterface.call("window.location.search.toString");
var urlVars:URLVariables = new URLVariables(wholeURL);
var myURL:String = urlVars.videoloc; //<--- Trouble, returning 'undefined'
errorBox.text = "videoloc="+urlVars.videoloc+"\nwholeURL="+wholeURL+"\nurlVars="+urlVars+"\nmyURL="+myURL; //<--- The reason I know it is returning 'undefined'
if (myURL) {
player.load(myURL);
player.play();
}
}
Ideally you should use a debugger to inspect the makeup of your URLVariables object.
If you're unable to do things the easy way, you could do this to trace its contents:
for (var parameter:String in urlVars) {
trace(parameter + "=" + urlVars[parameter]);
}
As you can see, you can step through every parameter inside urlVars using a for in loop.
I'm guessing videoLoc is your first parameter? Look at the results of this test of mine:
var address:String = "http://www.google.ca/search?q=test&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-GB:official&client=firefox-a";
var urlVars:URLVariables = new URLVariables(address);
for (var parameter:String in urlVars) {
trace(parameter + "=" + urlVars[parameter]);
}
The output of this is:
aq=t
rls=org.mozilla:en-GB:official
client=firefox-a
http://www.google.ca/search?q=test
ie=utf-8
oe=utf-8
See what happened to the q parameter? To fix this, use only the text past the ?
var address:String = "http://www.google.ca/search?q=test&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-GB:official&client=firefox-a";
var urlVars:URLVariables
= new URLVariables(address.substr(address.indexOf('?')+1));
for (var parameter:String in urlVars) {
trace(parameter + "=" + urlVars[parameter]);
}