An example : ADD 10 MORE BLACK BIRDS!
Bookmark following bookmarklet.
Go to http://chrome.angrybirds.com/
Wait for loading page. (Do not select a level here...)
Click the bookmarklet from your Bookmarks.
Select a level to play!
Original source code
( function () {
var RealXMLHttpRequest = XMLHttpRequest ;
var FakeXMLHttpRequest = function () {
this . _req = new RealXMLHttpRequest ();
};
FakeXMLHttpRequest . prototype = {
abort : function () {
this . _req . abort . apply ( this . _req , arguments );
},
getAllResponseHeaders : function () {
return this . _req . getAllResponseHeaders . apply ( this . _req , arguments );
},
open : function () {
this . _url = arguments [ 1 ];
this . _req . open . apply ( this . _req , arguments );
},
overrideMimeType : function () {
this . _req . overrideMimeType . apply ( this . _req , arguments );
},
send : function () {
this . _req . send . apply ( this . _req , arguments );
},
sendAsBinary : function () {
this . _req . sendAsBinary . apply ( this . _req , arguments );
},
setRequestHeader : function () {
this . _req . setRequestHeader . apply ( this . _req , arguments );
},
get multipart () {
return this . _req . multipart ;
},
set multipart ( value ) {
this . _req . multipart = value ;
},
get onreadystatechange () {
return this . _req . onreadystatechange ;
},
set onreadystatechange ( value ) {
this . _req . onreadystatechange = value ;
},
get readyState () {
return this . _req . readyState ;
},
get response () {
return this . _req . response ;
},
get responseText () {
return this . _hookResponseText ( this . _req . responseText );
},
get responseXML () {
return this . _req . responseXML ;
},
get status () {
return this . _req . status ;
},
get statusText () {
return this . _req . statusText ;
},
get upload () {
return this . _req . upload ;
},
get withCredentials () {
return this . _req . withCredentials ;
},
_hookResponseText : function ( responseText ) {
try {
if ( /Level [ 0-9 ] +.json$/ . test ( this . _url )) {
var jsonData = JSON . parse ( responseText );
jsonData = this . _modifyAngryBirdLevel ( jsonData );
responseText = JSON . stringify ( jsonData );
}
} catch ( ex ) {
}
return responseText ;
},
_modifyAngryBirdLevel : function ( jsonData ) {
// Add 10 more BIRD_BLACK.
for ( var i = 0 ; i < 10 ; i ++ ) {
jsonData . counts . birds ++ ;
jsonData . world [ " bird_ " + jsonData . counts . birds ] = {
" angle " : 0 ,
" id " : " BIRD_BLACK " ,
" x " : jsonData . world [ " bird_1 " ]. x ,
" y " : jsonData . world [ " bird_1 " ]. y
};
}
return jsonData ;
},
dummy : null
};
window . XMLHttpRequest = FakeXMLHttpRequest ;
})();
Principle: Hooking XMLHttpRequest
Angry Birds levels (Stage data) are defined with JSON file.
For example, "http://chrome.angrybirds.com/angrybirds/json/Level47.json"
The web app loads the JSON file when you start playing a level.
XMLHttpRequest
is used for loading the JSON file.
So, I hooked XMLHttpRequest
class to modify the level data.
XMLHttpRequest#responseText
returns modified JSON text data by my "_modifyAngryBirdLevel()
" method.
Recipes
You can also modify blocks. Following example converts stone and wood blocks to ice blocks.
_modifyAngryBirdLevel : function ( jsonData ) {
// ...
// Add 10 more BIRD_BLACK.
for ( var i = 1 ; i & lt ; jsonData . counts . blocks ; i ++ ) {
jsonData . world [ " block_ " + i ]. id = jsonData . world [ " block_ " + i ]. id . replace ( / ( STONE|WOOD ) _BLOCK/ , " ICE_BLOCK " );
}
return jsonData ;
},
You can also make your own custom levels!!
_modifyAngryBirdLevel : function ( jsonData ) {
// A very very simple level: 1 black bird vs 1 pig.
return {
" camera " : [
{
" bottom " : - 45 ,
" id " : " Slingshot " ,
" left " : - 60 ,
" right " : 4 ,
" top " : - 45 ,
" x " : 30 ,
" y " : - 4
},
{
" bottom " : - 45 ,
" id " : " Castle " ,
" left " : 10 ,
" right " : 60 ,
" top " : - 45 ,
" x " : 30 ,
" y " : - 4
}
],
" counts " : {
" birds " : 1 ,
" blocks " : 1
},
" id " : jsonData . id ,
" scoreEagle " : 40000 ,
" scoreGold " : 60000 ,
" scoreSilver " : 50000 ,
" theme " : " BACKGROUND_BLUE_GRASS " ,
" world " : {
" bird_1 " : {
" angle " : 0 ,
" id " : " BIRD_BLACK " ,
" x " : 10 ,
" y " : - 1
},
" block_1 " : {
" angle " : 0 ,
" id " : " PIG_BASIC_MEDIUM " ,
" x " : 50 ,
" y " : - 1
}
}
};
},
Note
I think ROVIO will encrypt all level files to avoid this hack ...
See also