In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

R&B Online

ガチンコオンラインチーム対戦シューティングゲームです。
更新履歴はコードの最終行にて。
Get Adobe Flash player
by o8que 03 Jul 2012

    Talk

    o8que at 06 Mar 2012 19:52
    補足: チャット荒らしのコメントをクリックして[+]で非表示フィルタ、[-]でフィルタ全削除 プレイ中にallをクリックでteamチャットとの切り替え チャット窓はバーをドラッグで移動、右下のグリップをドラッグでリサイズできます

    Tags

    Embed
/**
 * Copyright o8que ( http://wonderfl.net/user/o8que )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/sKs2
 */

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.utils.Timer;
    import net.user1.logger.Logger;
    import net.user1.reactor.Reactor;
    import net.wonderfl.utils.WonderflAPI;
/*    import ore.orelib.assets.Artist;
    import ore.orelib.assets.ScoreBoard;
    import ore.orelib.commons.Assets;
    import ore.orelib.commons.Chat;
    import ore.orelib.commons.Key;
    import ore.orelib.commons.Preloader;
    import ore.orelib.commons.Temp;
    import ore.orelib.data.Const;
    import ore.orelib.scenes.IScene;
    import ore.orelib.scenes.TitleScene;
*/    
    [SWF(width = "465", height = "465", frameRate = "45", backgroundColor = "0x000000")]
    public class Main extends Sprite {
        private var _reactor:Reactor;
        private var _api:WonderflAPI;
        private var _timestamp:Number;
        private var _synchronizer:Timer;
        private var _chat:Chat;
        private var _scoreBoard:ScoreBoard;
        private var _scene:IScene;
        
        private static const SERVER_ADDR:String = "tryunion.com";
        private static const SERVER_PORT:int = 80;
        
        public function Main() {
            Wonderfl.disable_capture();
            // Reactorの初期設定
            _reactor = new Reactor();
            _reactor.disableHTTPFailover();
            _reactor.getConnectionMonitor().sharePing(true);
            _reactor.getLog().setLevel(Logger.FATAL);
            //_reactor.getLog().setLevel(Logger.DEBUG);
            
            _api = new WonderflAPI(root.loaderInfo.parameters, root.loaderInfo.url.substring(root.loaderInfo.url.lastIndexOf("/") + 1, root.loaderInfo.url.lastIndexOf(".")));
            // サーバー接続・各アセット読み込み
            var preloader:Preloader = new Preloader(this);
            preloader.addReactorConnectionRequest(_reactor, Main.SERVER_ADDR, Main.SERVER_PORT);
            preloader.addLoaderRequest(Const.IMAGE_URL);
            preloader.addFontLoaderRequest(Const.FONT);
            preloader.addEventListener(Event.COMPLETE, init);
            preloader.load(String(_api.appID));
        }
        
        private function init(event:Event):void {
            var preloader:Preloader = event.currentTarget as Preloader;
            preloader.removeEventListener(event.type, arguments.callee);
            
            // 画像アセットの登録
            Assets.images[Const.IMAGE_LOADER_CONTROLS] = preloader.loaders[Const.IMAGE_URL];
            Assets.images[Const.IMAGE_RED_TURRET] = Artist.createTurrets(0xFF0000);
            Assets.images[Const.IMAGE_BLUE_TURRET] = Artist.createTurrets(0x0000FF);
            Assets.images[Const.IMAGE_RED_BULLET] = Artist.createBullets(0xFF0000);
            Assets.images[Const.IMAGE_BLUE_BULLET] = Artist.createBullets(0x0000FF);
            Assets.images[Const.IMAGE_INDICATOR] = Artist.createIndicator();
            Assets.images[Const.IMAGE_BACKGROUND] = Artist.createBackground(Const.STAGE_SIZE, Const.TEAMBASE_SIZE, Const.CONTROLPOINT_RADIUS);
            Assets.images[Const.IMAGE_HIT_EFFECT_ANIM] = Artist.createHitEffectAnimation();
            Assets.images[Const.IMAGE_KILLED_EFFECT_ANIM] = Artist.createKilledEffectAnimation();
            
            // 静的クラスの初期化
            Key.init(this);
            Temp.init(5);
            
            // サーバーと一定間隔で同期するようにする
            _timestamp = _reactor.getServer().getServerTime();
            _synchronizer = new Timer(10000, 0);
            _synchronizer.addEventListener(TimerEvent.TIMER, synchronize);
            _synchronizer.start();
            synchronize();
            
            stage.addChild(_chat = new Chat(_reactor, String(_api.appID) + ".c"));
            _chat.x = 233;
            _scoreBoard = new ScoreBoard(_reactor, _api);
            _scene = new TitleScene(this, true);
            addEventListener(Event.ENTER_FRAME, update);
        }
        
        private function synchronize(event:TimerEvent = null):void {
            if (_reactor.isReady()) { _reactor.getServer().syncTime(); }
        }
        
        private function update(event:Event):void {
            var serverTime:Number = _reactor.getServer().getServerTime();
            var gameTime:int = serverTime % Const.GAME_DURATION;
            _scoreBoard.update(gameTime);
            _scene.update(gameTime, Math.max(0, serverTime - _timestamp));
            _timestamp = serverTime;
        }
        
        public function changeScene(scene:IScene):void { _scene = scene; }
        public function get reactor():Reactor { return _reactor; }
        public function get api():WonderflAPI { return _api; }
        public function get chat():Chat { return _chat; }
        public function get scoreBoard():ScoreBoard { return _scoreBoard; }
    }
}
//package ore.orelib.scenes {
    //public 
    interface IScene {
        function update(gameTime:int, elapsedTime:int):void;
    }
//}
//package ore.orelib.scenes {
    import com.bit101.components.PushButton;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.text.TextField;
/*    import ore.orelib.assets.InstructionWindow;
    import ore.orelib.commons.CustomComps;
    import ore.orelib.commons.Labeler;
    import ore.orelib.data.Const;
*/    
    //public 
    class TitleScene extends Sprite implements IScene {
        private var _main:Main;
        private var _nameForm:TextField;
        private var _joinRedButton:PushButton;
        private var _joinBlueButton:PushButton;
        
        public function TitleScene(main:Main, showsInstruction:Boolean = false) {
            _main = main;
            _main.addChild(this);
            _main.reactor.getConnectionMonitor().setHeartbeatFrequency(10000);
            _main.reactor.getConnectionMonitor().setConnectionTimeout(50000);
            
            graphics.beginFill(0x000000);
            graphics.drawRect(0, 0, 465, 465);
            graphics.endFill();
            
            addChild(
                new Labeler().autoSize(Labeler.CENTER, Labeler.MIDDLE)
                .font(Const.FONT, -400, 400).fontColor(0xFFFFFF).fontSize(24)
                .size(232, 40).build("R&B Online")
            );
            addChild(_nameForm = CustomComps.createNameForm(150));
            _nameForm.x = 41; _nameForm.y = 45;
            _nameForm.addEventListener(Event.CHANGE, changeName);
            if (_main.reactor.isReady()) {
                _nameForm.text = validateName(_main.reactor.self().getAttribute(Const.ATTR_NAME));
            }
            changeName();
            _joinRedButton = new PushButton(this, 14, 75, "join Red", joinRed);
            _joinBlueButton = new PushButton(this, 118, 75, "join Blue", joinBlue);
            _joinRedButton.enabled = _joinBlueButton.enabled = false;
            addChild(_main.scoreBoard);
            _main.scoreBoard.visible = true;
            addChild(
                new Labeler().autoSize(Labeler.CENTER, Labeler.MIDDLE)
                .font(Const.FONT).fontColor(0xFFFFFF).fontSize(12).selectable()
                .pos(0, 435).size(465, 30).build(Const.HINTS[int(Const.HINTS.length * Math.random())])
            );
            if (showsInstruction) { addChild(new InstructionWindow()); }
        }
        
        private function changeName(event:Event = null):void {
            _main.chat.changeName(validateName(_nameForm.text));
        }
        
        private function validateName(name:String):String {
            var result:String = name;
            if (!result) { result = "Guest" + ((_main.reactor.isReady()) ? _main.reactor.self().getClientID() : "0"); }
            return result;
        }
        
        private function joinRed(event:MouseEvent):void {
            _main.reactor.self().setAttribute(Const.ATTR_TEAM, Const.TEAM_RED);
            startPlaying();
        }
        
        private function joinBlue(event:MouseEvent):void {
            _main.reactor.self().setAttribute(Const.ATTR_TEAM, Const.TEAM_BLUE);
            startPlaying();
        }
        
        private function startPlaying():void {
            _main.reactor.self().setAttribute(Const.ATTR_NAME, validateName(_nameForm.text));
            _main.reactor.self().setAttribute(Const.ATTR_SCORE, "0");
            _main.removeChild(this);
            _main.changeScene(new PlayingScene(_main));
        }
        
        public function update(gameTime:int, elapsedTime:int):void {
            var numDiff:int = _main.scoreBoard.numRedPlayers - _main.scoreBoard.numBluePlayers;
            _joinRedButton.enabled = _main.reactor.isReady() && numDiff < 1;
            _joinBlueButton.enabled = _main.reactor.isReady() && numDiff > -1;
        }
    }
//}
//package ore.orelib.scenes {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.ui.Keyboard;
    import net.user1.reactor.filters.AttributeComparison;
    import net.user1.reactor.filters.AttributeFilter;
    import net.user1.reactor.filters.CompareType;
    import net.user1.reactor.Room;
    import net.user1.reactor.RoomSettings;
/*    import ore.orelib.actors.BulletManager;
    import ore.orelib.actors.EffectManager;
    import ore.orelib.actors.TurretManager;
    import ore.orelib.assets.HUD;
    import ore.orelib.commons.Assets;
    import ore.orelib.commons.Key;
    import ore.orelib.commons.sint;
    import ore.orelib.commons.Temp;
    import ore.orelib.data.Const;
    import ore.orelib.logic.Camera;
    import ore.orelib.logic.ControlPoint;
    import ore.orelib.logic.Player;
*/    
    //public 
    class PlayingScene extends Sprite implements IScene {
        private var _main:Main;
        private var _room:Room;
        private var _isActive:Boolean;
        private var _leaveCount:sint;
        // データ関連
        private var _player:Player;
        private var _turrets:TurretManager;
        private var _bullets:BulletManager;
        private var _effects:EffectManager;
        private var _controlPoint:ControlPoint;
        // 表示関連
        private var _camera:Camera;
        private var _screen:BitmapData;
        private var _hud:HUD;
        
        public function PlayingScene(main:Main) {
            _main = main;
            _main.addChild(this);
            _main.reactor.getConnectionMonitor().setHeartbeatFrequency(1000);
            _main.reactor.getConnectionMonitor().setConnectionTimeout(5000);
            
            var roomSettings:RoomSettings = new RoomSettings();
            roomSettings.password = String(_main.api.apiKey);
            roomSettings.removeOnEmpty = false;
            _room = _main.reactor.getRoomManager().createRoom(String(_main.api.appID) + ".g", roomSettings);
            
            _isActive = true;
            _leaveCount = new sint(5000);
            addEventListener(Event.ACTIVATE, activate);
            addEventListener(Event.DEACTIVATE, deactivate);
            
            _player = new Player(_main.reactor.self(), _room);
            _player.respawn(Math.max(500, Const.SETUP_DURATION - (_main.reactor.getServer().getServerTime() % Const.GAME_DURATION)));
            _turrets = new TurretManager(_room);
            _bullets = new BulletManager(_main.reactor.self(), _room);
            _effects = new EffectManager(_room);
            _controlPoint = new ControlPoint();
            
            _camera = new Camera();
            addChild(new Bitmap(_screen = new BitmapData(465, 465, false, 0x000000)));
            addChild(_hud = new HUD(_main.reactor.self(), _room, _player, _controlPoint));
            addChild(_main.scoreBoard);
            _main.scoreBoard.register();
            _main.scoreBoard.visible = false;
            
            stage.focus = null;
            // チームチャットを有効にする
            var filters:AttributeFilter = new AttributeFilter();
            filters.addComparison(new AttributeComparison(Const.ATTR_TEAM, _main.reactor.self().getAttribute(Const.ATTR_TEAM), CompareType.EQUAL));
            _main.chat.enableTeamChat(_room, filters, (_main.reactor.self().getAttribute(Const.ATTR_TEAM) == Const.TEAM_RED) ? Const.COLOR_RED : Const.COLOR_BLUE);
            _room.join(String(_main.api.apiKey));
        }
        
        private function activate(event:Event):void { _isActive = true; _leaveCount.value = 5000; }
        private function deactivate(event:Event):void { _isActive = false; }
        
        public function update(gameTime:int, elapsedTime:int):void {
            // 接続が切れる・FPがフォーカスを失う・Escキーが押されるかしたら、タイトルに戻る
            if (!_isActive) { _leaveCount.value -= elapsedTime; }
            if (!_main.reactor.isReady() || Key.pressed(Keyboard.ESCAPE) || _leaveCount.value < 0) {
                backToTitle();
                return;
            }
            
            // ゲーム開始(セットアップ終了)ならスコアリセット
            // ゲーム終了(セットアップ開始)なら強制リスポン
            if (gameTime - elapsedTime < Const.SETUP_DURATION && gameTime >= Const.SETUP_DURATION) {
                _player.resetScore();
            } else if (gameTime < elapsedTime) {
                _player.respawn(Const.SETUP_DURATION - gameTime);
            }
            
            // 更新
            _player.update(gameTime, elapsedTime, Math.atan2(mouseY - 232.5, mouseX - 232.5));
            _turrets.update(gameTime);
            _bullets.update(gameTime, _player.pos, _main.reactor.self().getAttribute(Const.ATTR_TEAM));
            _effects.update();
            _controlPoint.update(elapsedTime, _player);
            
            // 描画
            _camera.update(_player, _turrets);
            _screen.lock();
            _screen.fillRect(Temp.rectangle(0, 0, 465, 465), 0x000000);
            _screen.copyPixels(Assets.images[Const.IMAGE_BACKGROUND], Temp.rectangle(0, 0, Const.STAGE_SIZE, Const.STAGE_SIZE), Temp.point(-_camera.rect.x, -_camera.rect.y));
            _bullets.draw(_camera, _screen);
            _turrets.draw(_camera, _screen, _main.reactor.self().getAttribute(Const.ATTR_TEAM));
            _player.draw(_camera, _screen);
            _effects.draw(_camera, _screen);
            _controlPoint.draw(_camera, _screen);
            _screen.unlock();
            
            _hud.update(gameTime, _main.scoreBoard.redTeamScore, _main.scoreBoard.blueTeamScore);
            _main.scoreBoard.visible = Key.isDown(Keyboard.SPACE) || gameTime < Const.SETUP_DURATION;
            
            // Pingを安定させるハック
            _main.reactor.self().setAttribute(Const.ATTR_PING, "", null, false);
        }
        
        private function backToTitle():void {
            _main.scoreBoard.unregister();
            _main.chat.disableTeamChat();
            _room.leave();
            
            removeEventListener(Event.DEACTIVATE, deactivate);
            _player.removeListeners();
            _turrets.removeListeners();
            _bullets.removeListeners();
            _effects.removeListeners();
            _hud.removeListeners();
            
            _main.removeChild(this);
            _main.changeScene(new TitleScene(_main));
        }
    }
//}
//package ore.orelib.logic {
    import flash.display.BitmapData;
    import flash.geom.Point;
    import flash.ui.Keyboard;
    import net.user1.reactor.IClient;
    import net.user1.reactor.Room;
/*    import ore.orelib.actors.Turret;
    import ore.orelib.commons.EventManager;
    import ore.orelib.commons.Key;
    import ore.orelib.commons.sint;
    import ore.orelib.commons.Temp;
    import ore.orelib.commons.UPCConv;
    import ore.orelib.data.Const;
    import ore.orelib.events.CaptureEvent;
    import ore.orelib.events.HitEvent;
    import ore.orelib.events.KilledEvent;
    import ore.orelib.events.ShootEvent;
*/    
    //public 
    class Player {
        private var _self:IClient;
        private var _room:Room;
        private var _view:Turret;
        // ステータス関連
        private var _score:sint;
        private var _hp:sint;
        private var _en:sint;
        private var _barrelCoolDown:Boolean;
        private var _fireCount:int;
        private var _respawnCount:int;
        private var _respawnTime:int;
        private var _nemesisID:String;
        // 移動関連
        private var _position:Point;
        private var _velocity:Point;
        private var _angle:Number;
        // 通信関連
        private var _sendCount:int;
        private var _uidForBullet:int;
        
        public function Player(self:IClient, room:Room) {
            _self = self;
            _room = room;
            _view = new Turret(_self);
            _score = new sint(0);
            _hp = new sint(Const.PLAYER_HP);
            _en = new sint(Const.PLAYER_EN);
            _barrelCoolDown = false;
            _fireCount = _respawnCount = 0;
            _respawnTime = 1;
            _nemesisID = "";
            _position = new Point(0, 0);
            _velocity = new Point(0, 0);
            _angle = 0;
            _sendCount = Const.PLAYER_SEND_INTERVAL;
            _uidForBullet = 0;
            
            _room.addMessageListener(Const.MESSAGE_KILLED, mayKillOther);
            EventManager.instance.addEventListener(HitEvent.HIT, takeDamage);
            EventManager.instance.addEventListener(CaptureEvent.CAPTURE, captureControlPoint);
        }
        
        /** 誰かが倒された時に、倒したのが自分ならスコアを得る */
        private function mayKillOther(from:IClient, x_y:String, killerID:String):void {
            if (killerID == _self.getClientID()) {
                _score.value += Const.SCORE_KILL;
                _self.setAttribute(Const.ATTR_SCORE, _score.value.toString());
                _hp.value = Math.min(_hp.value + Const.RESTORE_KILL, Const.PLAYER_HP);
            }
        }
        
        /** 敵の弾に当たってダメージを受けた際の処理 */
        private function takeDamage(event:HitEvent):void {
            // dispatchEventはBulletクラスで行う
            _room.sendMessage(Const.MESSAGE_HIT, false, null,
                Protocol.encode_x_y(event.x, event.y),
                UPCConv.encode(int(event.bulletID))
            );
            if (--_hp.value <= 0) { onKilledBy(event.ownerID); }
        }
        
        /** 自分が倒された時の処理 */
        private function onKilledBy(nemesisID:String):void {
            _nemesisID = nemesisID;
            _room.sendMessage(Const.MESSAGE_KILLED, false, null, Protocol.encode_x_y(_position.x, _position.y), nemesisID);
            EventManager.instance.dispatchEvent(new KilledEvent(_position.x, _position.y, _self.getClientID(), nemesisID));
            respawn(Const.PLAYER_RESPAWN_TIME);
        }
        
        /** 占領地点を占領したらスコアを得る */
        private function captureControlPoint(event:CaptureEvent):void {
            _score.value += Const.SCORE_CAPTURE;
            _self.setAttribute(Const.ATTR_SCORE, _score.value.toString());
            _hp.value = Math.min(_hp.value + Const.RESTORE_CAPTURE, Const.PLAYER_HP);
        }
        
        /** スコアをリセットする */
        public function resetScore():void {
            _score.value = 0;
            _self.setAttribute(Const.ATTR_SCORE, "0");
        }
        
        /** リスポンする */
        public function respawn(setupTime:int):void {
            _hp.value = _en.value = 0;
            _respawnCount = _respawnTime = setupTime;
            
            var baseTopLeft:int = (_self.getAttribute(Const.ATTR_TEAM) == Const.TEAM_RED) ? 0 : Const.STAGE_SIZE - Const.TEAMBASE_SIZE;
            _position.setTo(baseTopLeft + Const.TEAMBASE_SIZE * (0.2 + 0.6 * Math.random()), baseTopLeft + Const.TEAMBASE_SIZE * (0.2 + 0.6 * Math.random()));
            _velocity.setTo(0, 0);
            _self.setAttribute(Const.ATTR_STATES, Protocol.encodeStates(_position.x, _position.y, 0, 0, 0, _angle, _hp.value), _room.getRoomID());
        }
        
        /** セットアップ終了時に初期化 */
        private function init():void {
            _hp.value = Const.PLAYER_HP;
            _en.value = Const.PLAYER_EN;
            _barrelCoolDown = false;
            _fireCount = 0;
            _nemesisID = "";
        }
        
        public function update(gameTime:int, elapsedTime:int, angle:Number):void {
            _angle = angle;
            
            // セットアップ中でなければ、移動・攻撃が可能
            if (_respawnCount > 0) {
                _respawnCount -= elapsedTime;
                if (_respawnCount <= 0) { init(); }
            } else {
                move();
                chargeEnergy(elapsedTime);
                shoot(gameTime, elapsedTime);
            }
            
            // ステージ外に出ていたら自滅
            if (!Collision.hitTestCircleToRect(_position, 1, Temp.rectangle(0, 0, Const.STAGE_SIZE, Const.STAGE_SIZE))) {
                _score.value = Math.max(0, _score.value - Const.SCORE_KILL);
                _self.setAttribute(Const.ATTR_SCORE, _score.value.toString());
                onKilledBy("");
            }
            
            // 一定間隔で状態送信
            _sendCount -= elapsedTime;
            if (_sendCount < 0) {
                _sendCount = Const.PLAYER_SEND_INTERVAL;
                _self.setAttribute(Const.ATTR_STATES, Protocol.encodeStates(_position.x, _position.y, _velocity.x, _velocity.y, gameTime, _angle, _hp.value), _room.getRoomID());
            }
            
            // ビューの更新
            _view.changeStates(_position.x, _position.y, 0, 0, 0, angle, _hp.value, _en.value);
            _view.update(gameTime);
        }
        
        private function move():void {
            _velocity.setTo(_velocity.x * 0.99, _velocity.y * 0.99);
            if (Key.isDown(Keyboard.W)) { _velocity.y -= Const.PLAYER_ACCEL; }
            if (Key.isDown(Keyboard.S)) { _velocity.y += Const.PLAYER_ACCEL; }
            if (Key.isDown(Keyboard.A)) { _velocity.x -= Const.PLAYER_ACCEL; }
            if (Key.isDown(Keyboard.D)) { _velocity.x += Const.PLAYER_ACCEL; }
            if (_velocity.x * _velocity.x + _velocity.y * _velocity.y > Const.PLAYER_SQ_SPEED) { _velocity.normalize(Const.PLAYER_SPEED); }
            _position.offset(_velocity.x, _velocity.y);
        }
        
        private function chargeEnergy(elapsedTime:int):void {
            // 普段はエネルギー回復量1.5倍
            var chargeAmount:int = elapsedTime * ((_barrelCoolDown) ? 1 : 1.5);
            _en.value = Math.min(_en.value + chargeAmount, Const.PLAYER_EN);
            if (_en.value == Const.PLAYER_EN) { _barrelCoolDown = false; }
        }
        
        private function shoot(gameTime:int, elapsedTime:int):void {
            if (_fireCount > 0) { _fireCount -= elapsedTime; }
            if (Key.isDown(Key.MOUSE_LEFT) && !_barrelCoolDown && _fireCount <= 0) {
                _en.value -= Const.PLAYER_EN_COST;
                if (_en.value <= 0) {
                    _en.value = 0;
                    _barrelCoolDown = true;
                }
                _fireCount += Const.PLAYER_FIRERATE;
                _uidForBullet = Protocol.getNextUid(_uidForBullet);
                
                _room.sendMessage(
                    Const.MESSAGE_SHOOT, false, null,
                    Protocol.encode_x_y(_position.x, _position.y),
                    UPCConv.encode(gameTime),
                    Protocol.encode_angle_uid(_angle, _uidForBullet)
                );
                EventManager.instance.dispatchEvent(new ShootEvent(_position.x, _position.y, _angle, gameTime, _uidForBullet));
            } else if(_fireCount < 0) {
                _fireCount = 0;
            }
        }
        
        public function draw(camera:Camera, screen:BitmapData):void {
            _view.draw(camera, screen, _self.getAttribute(Const.ATTR_TEAM), _barrelCoolDown);
        }
        
        public function removeListeners():void {
            _room.removeMessageListener(Const.MESSAGE_KILLED, mayKillOther);
            EventManager.instance.removeEventListener(HitEvent.HIT, takeDamage);
            EventManager.instance.removeEventListener(CaptureEvent.CAPTURE, captureControlPoint);
        }
        
        public function get respawnRate():Number { return 1 - Math.max(0, _respawnCount / _respawnTime); }
        public function get nemesisID():String { return _nemesisID; }
        public function get pos():Point { return _position; }
    }
//}
//package ore.orelib.logic {
/*    import ore.orelib.commons.UPCConv;
    import ore.orelib.data.Const;
*/    
    //public 
    class Protocol {
        public static function encodeStates(x:int, y:int, vx:Number, vy:Number, timestamp:int, angle:Number, hp:int):String {
            return encode_x_y(x, y) + "," + encode_timestamp_vx(timestamp, vx) + "," + encode_angle_vy_hp(angle, vy, hp);
        }
        
        public static function encode_x_y(x:int, y:int):String {
            return UPCConv.encode((encodePos(x) << 12) + encodePos(y)); //(12,12)
        }
        private static function encode_timestamp_vx(timestamp:int, vx:Number):String {
            return UPCConv.encode((timestamp << 9) + encodeSpeed(vx)); //(19,9)
        }
        private static function encode_angle_vy_hp(angle:Number, vy:Number, hp:int):String {
            return UPCConv.encode((encodeAngle(angle) << 14) + (encodeSpeed(vy) << 5) + hp); //(13,9,5)
        }
        
        private static function encodePos(value:int):int { return value + 1000; }
        private static function encodeSpeed(value:Number):int { return int((value + Const.PLAYER_SPEED) * Const.FRAME_RATE); }
        private static function encodeAngle(value:Number):int { return int((value + Math.PI) * 1000); }
        
        public static function decodeX(x_y:int):int { return (x_y >> 12) - 1000; }
        public static function decodeY(x_y:int):int { return (x_y & 0xFFF) - 1000; }
        public static function decodeVx(timestamp_vx:int):int { return (timestamp_vx & 0x1FF) - Const.PLAYER_SPEED_PER_SECOND; }
        public static function decodeVy(angle_vy_hp:int):int { return ((angle_vy_hp >> 5) & 0x1FF) - Const.PLAYER_SPEED_PER_SECOND; }
        public static function decodeTimestamp(timestamp_vx:int):int { return timestamp_vx >> 9; }
        public static function decodeTurretAngle(angle_vy_hp:int):Number { return ((angle_vy_hp >> 14) / 1000) - Math.PI; }
        public static function decodeHp(angle_vy_hp:int):int { return angle_vy_hp & 0x1F; }
        
        public static function getNextUid(value:int):int { return (value + 1) & 0xF; }
        public static function getBulletId(ownerID:String, uid:int):String { return ((int(ownerID) << 4) + uid).toString(); }
        
        public static function encode_angle_uid(angle:Number, uid:int):String {
            return UPCConv.encode((encodeAngle(angle) << 4) + uid); //(13,4)
        }
        
        public static function decodeBulletAngle(angle_uid:int):Number { return ((angle_uid >> 4) / 1000) - Math.PI; }
        public static function decodeBulletUid(angle_uid:int):int { return angle_uid & 0xF; }
    }
//}
//package ore.orelib.logic {
    import flash.display.BitmapData;
    import flash.geom.Matrix;
    import flash.geom.Point;
/*    import ore.orelib.commons.Assets;
    import ore.orelib.commons.EventManager;
    import ore.orelib.commons.Temp;
    import ore.orelib.data.Const;
    import ore.orelib.events.CaptureEvent;
*/    
    //public 
    class ControlPoint {
        private var _position:Point;
        private var _captureCount:int;
        
        public function ControlPoint() {
            _position = new Point(Const.STAGE_SIZE / 2, Const.STAGE_SIZE / 2);
            _captureCount = Const.CONTROLPOINT_CAPTURE_TIME;
        }
        
        public function update(elapsedTime:int, player:Player):void {
            if (Collision.hitTestCircleToCircle(player.pos, Const.TURRET_RADIUS, _position, Const.CONTROLPOINT_RADIUS)) {
                _captureCount -= elapsedTime;
                if (_captureCount < 0) {
                    _captureCount += Const.CONTROLPOINT_CAPTURE_TIME;
                    EventManager.instance.dispatchEvent(new CaptureEvent());
                }
            } else {
                _captureCount = Const.CONTROLPOINT_CAPTURE_TIME;
            }
        }
        
        public function draw(camera:Camera, screen:BitmapData):void {
            // 画面内なら指示器を表示しない
            if (Collision.hitTestCircleToRect(_position, Const.CONTROLPOINT_RADIUS, camera.rect)) { return; }
            
            var matrix:Matrix = Temp.matrix(1, 0, 0, 1, 100, -5);
            matrix.rotate(Math.atan2(_position.y - camera.pos.y, _position.x - camera.pos.x));
            matrix.translate(232.5, 232.5);
            screen.draw(Assets.images[Const.IMAGE_INDICATOR], matrix, Temp.colorTransform(), null, null, true);
        }
        
        public function get captureRate():Number { return 1 - Math.max(0, _captureCount / Const.CONTROLPOINT_CAPTURE_TIME); }
    }
//}
//package ore.orelib.logic {
    import flash.geom.Point;
    import flash.geom.Rectangle;
/*    import ore.orelib.actors.Turret;
    import ore.orelib.actors.TurretManager;
*/    
    //public 
    class Camera {
        private var _position:Point;
        private var _rect:Rectangle;
        
        public function Camera() {
            _position = new Point();
            _rect = new Rectangle();
        }
        
        public function update(player:Player, turrets:TurretManager):void {
            var nemesis:Turret = turrets.getTurret(player.nemesisID);
            // プレイヤーを倒した相手が生存していたら、その相手をターゲットにする
            if (nemesis && nemesis.isAlive) {
                _position.setTo(nemesis.x, nemesis.y);
                _rect.setTo(int(nemesis.x) - 232, int(nemesis.y) - 232, 465, 465);
            } else {
                _position.setTo(player.pos.x, player.pos.y);
                _rect.setTo(int(player.pos.x) - 232, int(player.pos.y) - 232, 465, 465);
            }
        }
        
        public function get pos():Point { return _position; }
        public function get rect():Rectangle { return _rect; }
    }
//}
//package ore.orelib.logic {
    import flash.geom.Point;
    import flash.geom.Rectangle;
/*    import ore.orelib.commons.Temp;
*/    
    //public 
    class Collision {
        
        /** 円と円の当たり判定を行う */
        public static function hitTestCircleToCircle(circle1Center:Point, circle1Radius:Number, circle2Center:Point, circle2Radius:Number):Boolean {
            var dx:Number = circle2Center.x - circle1Center.x;
            var dy:Number = circle2Center.y - circle1Center.y;
            var radiusSum:Number = circle1Radius + circle2Radius;
            return dx * dx + dy * dy <= radiusSum * radiusSum;
        }
        
        /** 円と長方形の当たり判定を行う */
        public static function hitTestCircleToRect(circleCenter:Point, circleRadius:Number, rect:Rectangle):Boolean {
            var sqDist:Number = 0;
            var d:Number = 0;
            
            if (circleCenter.x < rect.left) {
                d = rect.left - circleCenter.x;
                sqDist += d * d;
            } else if (circleCenter.x > rect.right) {
                d = circleCenter.x - rect.right;
                sqDist += d * d;
            }
            
            if (circleCenter.y < rect.top) {
                d = rect.top - circleCenter.y;
                sqDist += d * d;
            } else if (circleCenter.y > rect.bottom) {
                d = circleCenter.y - rect.bottom;
                sqDist += d * d;
            }
            
            return sqDist <= circleRadius * circleRadius;
        }
        
        /** 線分から点への最近接点を取得する(結果はTemp.pointで返す) */
        public static function getClosestPointLineToPoint(startLine:Point, endLine:Point, point:Point):Point {
            var se:Point = Temp.point(endLine.x - startLine.x, endLine.y - startLine.y);
            var sp:Point = Temp.point(point.x - startLine.x, point.y - startLine.y);
            var t:Number = Math.min(Math.max(0, (sp.x * se.x + sp.y * se.y) / (se.x * se.x + se.y * se.y)), 1);
            return Temp.point(startLine.x + se.x * t, startLine.y + se.y * t);
        }
    }
//}
//package ore.orelib.actors {
    import flash.display.BitmapData;
    import flash.filters.GlowFilter;
    import flash.geom.Point;
    import flash.text.TextField;
    import net.user1.reactor.IClient;
/*    import ore.orelib.commons.Assets;
    import ore.orelib.commons.Labeler;
    import ore.orelib.commons.Temp;
    import ore.orelib.data.Const;
    import ore.orelib.logic.Camera;
    import ore.orelib.logic.Collision;
*/    
    //public 
    class Turret {
        private var _client:IClient;
        private var _name:TextField;
        private var _imageIndex:int;
        private var _hp:int;
        private var _en:int;
        // 移動関連(推測航法)
        private var _currentGameTime:int;
        private var _currentPosition:Point;
        private var _previousPosition:Point;
        private var _timestamp:int;
        private var _predictedPosition:Point;
        private var _predictedVelocity:Point;
        private var _predictedTimestamp:int;
        private var _splinePoints:Vector.<Point>;
        
        public function Turret(client:IClient) {
            _client = client;
            _name = new Labeler().align(Labeler.CENTER)
                .filters([new GlowFilter(0x000000, 1, 2, 2)])
                .font(Const.FONT, -400, 400).fontColor(0xFFFFFF).fontSize(10)
                .size(160, 20).build("");
            _imageIndex = _hp = _en = _currentGameTime = 0;
            _currentPosition = new Point(-500, -500);
            _previousPosition = new Point(-500, -500);
            _predictedPosition = new Point(-500, -500);
            _predictedVelocity = new Point(0, 0);
            _timestamp = _predictedTimestamp = 0;
            _splinePoints = new Vector.<Point>(4, true);
            for (var i:int = 0; i < 4; i++) {
                _splinePoints[i] = new Point(0, 0);
            }
        }
        
        public function changeStates(x:int, y:int, vx:int, vy:int, timestamp:int, angle:Number, hp:int, en:int = 0):void {
            // 初期化直後は収束期間なしで位置を確定するようにする
            if (_timestamp == 0) { timestamp = 0; }
            
            _timestamp = _currentGameTime;
            _predictedPosition.setTo(x, y);
            _predictedVelocity.setTo(vx, vy);
            _predictedTimestamp = timestamp;
            // 予測時間が0の場合は、収束期間なしで位置を確定する
            if (_predictedTimestamp > 0) {
                _splinePoints[0].copyFrom(_previousPosition);
                _splinePoints[1].copyFrom(_currentPosition);
                var targetTime:Number = (_timestamp + Const.TURRET_CONVERGENCE_PERIOD - _predictedTimestamp) / 1000;
                _splinePoints[2].setTo(_predictedPosition.x + _predictedVelocity.x * targetTime, _predictedPosition.y + _predictedVelocity.y * targetTime);
                _splinePoints[3].setTo(_splinePoints[2].x + _predictedVelocity.x, _splinePoints[2].y + _predictedVelocity.y);
            } else {
                _previousPosition.copyFrom(_predictedPosition);
                _currentPosition.copyFrom(_predictedPosition);
            }
            _imageIndex = Math.round((angle + Math.PI) * 36 / Math.PI) % 72;
            _hp = hp; _en = en;
        }
        
        public function update(gameTime:int):void {
            _currentGameTime = gameTime;
            _previousPosition.copyFrom(_currentPosition);
            var elapsedTime:Number;
            // 収束期間ありで、収束期間中ならスプライン補間で移動
            if ((_predictedTimestamp > 0) && (_currentGameTime - _timestamp < Const.TURRET_CONVERGENCE_PERIOD)) {
                elapsedTime = (_currentGameTime - _timestamp) / Const.TURRET_CONVERGENCE_PERIOD;
                _currentPosition.setTo(
                    calculateSplineValue(_splinePoints[0].x, _splinePoints[1].x, _splinePoints[2].x, _splinePoints[3].x, elapsedTime),
                    calculateSplineValue(_splinePoints[0].y, _splinePoints[1].y, _splinePoints[2].y, _splinePoints[3].y, elapsedTime)
                );
            } else {
                elapsedTime = (_currentGameTime - _predictedTimestamp) / 1000;
                _currentPosition.setTo(
                    _predictedPosition.x + _predictedVelocity.x * elapsedTime,
                    _predictedPosition.y + _predictedVelocity.y * elapsedTime
                );
            }
        }
        
        // Catmull-Rom spline interpolation
        private function calculateSplineValue(n0:Number, n1:Number, n2:Number, n3:Number, t:Number):Number {
            return 0.5 * (t * (t * (t * (-n0 + 3 * n1 - 3 * n2 + n3) + (2 * n0 - 5 * n1 + 4 * n2 - n3)) + (-n0 + n2)) + 2 * n1);
        }
        
        public function draw(camera:Camera, screen:BitmapData, selfTeam:String, barrelCoolDown:Boolean = false):void {
            // 画面外なら描画しない
            if (!Collision.hitTestCircleToRect(_currentPosition, Const.TURRET_RADIUS, camera.rect)) { return; }
            
            var relativePosition:Point = Temp.point(int(_currentPosition.x) - camera.rect.left, int(_currentPosition.y) - camera.rect.top);
            // 本体
            screen.copyPixels(
                Assets.images[(_client.getAttribute(Const.ATTR_TEAM) == Const.TEAM_RED) ? Const.IMAGE_RED_TURRET : Const.IMAGE_BLUE_TURRET][_imageIndex],
                Temp.rectangle(0, 0, 64, 64),
                Temp.point(relativePosition.x - 32, relativePosition.y - 32)
            );
            // 名前
            _name.text = _client.getAttribute(Const.ATTR_NAME) + " [" + _client.getPing() + "]";
            screen.draw(_name, Temp.matrix(1, 0, 0, 1, relativePosition.x - 80, relativePosition.y - 44), Temp.colorTransform());
            // HPゲージ
            if (_client.getAttribute(Const.ATTR_TEAM) == selfTeam) {
                var hpRate:Number = Math.min(Math.max(0, _hp / Const.PLAYER_HP), 1);
                screen.fillRect(Temp.rectangle(relativePosition.x - 32, relativePosition.y + 32, 64, 3), 0xFFFF0000);
                screen.fillRect(Temp.rectangle(relativePosition.x - 32, relativePosition.y + 32, 64 * hpRate, 3), 0xFF00FF00);
            }
            // ENゲージ
            if (_client.isSelf()) {
                var enRate:Number = Math.min(Math.max(0, _en / Const.PLAYER_EN), 1);
                screen.fillRect(Temp.rectangle(relativePosition.x - 32, relativePosition.y + 37, 64, 3), 0xFF444400);
                screen.fillRect(Temp.rectangle(relativePosition.x - 32, relativePosition.y + 37, 64 * enRate, 3), (barrelCoolDown) ? 0xFFFF8800 : 0xFFFFFF00);
            }
        }
        
        public function get isAlive():Boolean { return _hp > 0; }
        public function get x():Number { return _currentPosition.x; }
        public function get y():Number { return _currentPosition.y; }
    }
//}
//package ore.orelib.actors {
    import flash.display.BitmapData;
    import flash.utils.Dictionary;
    import net.user1.reactor.Attribute;
    import net.user1.reactor.IClient;
    import net.user1.reactor.Room;
    import net.user1.reactor.RoomEvent;
/*    import ore.orelib.commons.UPCConv;
    import ore.orelib.data.Const;
    import ore.orelib.logic.Camera;
    import ore.orelib.logic.Protocol;
*/    
    //public 
    class TurretManager {
        private var _room:Room;
        private var _turrets:Dictionary;
        
        public function TurretManager(room:Room) {
            _room = room;
            _turrets = new Dictionary();
            
            _room.addEventListener(RoomEvent.ADD_OCCUPANT, addOccupantHandler);
            _room.addEventListener(RoomEvent.REMOVE_OCCUPANT, removeOccupantHandler);
            _room.addEventListener(RoomEvent.UPDATE_CLIENT_ATTRIBUTE, updateClientAttrHandler);
        }
        
        /** 他人が参加した時の処理 */
        private function addOccupantHandler(event:RoomEvent):void {
            var client:IClient = event.getClient();
            if (client.isSelf()) { return; }
            
            var turret:Turret = new Turret(client);
            _turrets[client.getClientID()] = turret;
            var states:String = client.getAttribute(Const.ATTR_STATES, _room.getRoomID());
            if (states) { changeTurretStates(turret, states); }
        }
        
        /** 他人が退室した時の処理 */
        private function removeOccupantHandler(event:RoomEvent):void {
            delete _turrets[event.getClientID()];
        }
        
        /** 他人の状態が変化した時の処理 */
        private function updateClientAttrHandler(event:RoomEvent):void {
            var client:IClient = event.getClient();
            if (client.isSelf()) { return; }
            
            var turret:Turret = _turrets[client.getClientID()];
            var attr:Attribute = event.getChangedAttr();
            if (attr.name == Const.ATTR_STATES) { changeTurretStates(turret, attr.value); }
        }
        
        private function changeTurretStates(turret:Turret, states:String):void {
            var delimiter1:int = states.indexOf(",");
            var delimiter2:int = states.lastIndexOf(",");
            var x_y:int = UPCConv.decode(states.substring(0, delimiter1));
            var timestamp_vx:int = UPCConv.decode(states.substring(delimiter1 + 1, delimiter2));
            var angle_vy_hp:int = UPCConv.decode(states.substring(delimiter2 + 1));
            turret.changeStates(
                Protocol.decodeX(x_y),
                Protocol.decodeY(x_y),
                Protocol.decodeVx(timestamp_vx),
                Protocol.decodeVy(angle_vy_hp),
                Protocol.decodeTimestamp(timestamp_vx),
                Protocol.decodeTurretAngle(angle_vy_hp),
                Protocol.decodeHp(angle_vy_hp)
            );
        }
        
        public function update(gameTime:int):void {
            for each(var turret:Turret in _turrets) {
                turret.update(gameTime);
            }
        }
        
        public function draw(camera:Camera, screen:BitmapData, selfTeam:String):void {
            for each(var turret:Turret in _turrets) {
                turret.draw(camera, screen, selfTeam);
            }
        }
        
        public function removeListeners():void {
            _room.removeEventListener(RoomEvent.ADD_OCCUPANT, addOccupantHandler);
            _room.removeEventListener(RoomEvent.REMOVE_OCCUPANT, removeOccupantHandler);
            _room.removeEventListener(RoomEvent.UPDATE_CLIENT_ATTRIBUTE, updateClientAttrHandler);
        }
        
        public function getTurret(clientID:String):Turret { return _turrets[clientID]; }
    }
//}
//package ore.orelib.actors {
    import flash.display.BitmapData;
    import flash.geom.Point;
    import flash.geom.Rectangle;
/*    import ore.orelib.commons.Assets;
    import ore.orelib.commons.EventManager;
    import ore.orelib.commons.Temp;
    import ore.orelib.data.Const;
    import ore.orelib.events.HitEvent;
    import ore.orelib.logic.Camera;
    import ore.orelib.logic.Collision;
*/    
    //public 
    class Bullet {
        private var _ownerID:String;
        private var _bulletID:String;
        private var _currentPosition:Point;
        private var _previousPosition:Point;
        private var _velocity:Point;
        private var _imageIndex:int;
        private var _spawnPosition:Point;
        private var _spawnTime:int;
        private var _team:String;
        private var _exists:Boolean;
        
        public function Bullet() {
            _ownerID = "";
            _bulletID = "";
            _currentPosition = new Point();
            _previousPosition = new Point();
            _velocity = new Point();
            _imageIndex = 0;
            _spawnPosition = new Point();
            _spawnTime = 0;
            _team = "";
            _exists = false;
        }
        
        public function init(ownerID:String, bulletID:String, x:int, y:int, angle:Number, spawnTime:int, team:String):void {
            _ownerID = ownerID;
            _bulletID = bulletID;
            _currentPosition.setTo(x, y);
            _previousPosition.setTo(x, y);
            _velocity.setTo(Const.BULLET_SPEED * Math.cos(angle), Const.BULLET_SPEED * Math.sin(angle));
            _imageIndex = Math.round((angle + Math.PI) * 36 / Math.PI) % 36;
            _spawnPosition.setTo(x, y);
            _spawnTime = spawnTime;
            _team = team;
            _exists = true;
        }
        
        public function update(gameTime:int, playerPos:Point, selfTeam:String):void {
            var elapsedTime:int = gameTime - _spawnTime;
            // 生存時間外なら削除
            if (elapsedTime < 0 || Const.BULLET_LIFETIME < elapsedTime) {
                _exists = false; return;
            }
            
            _previousPosition.copyFrom(_currentPosition);
            _currentPosition.setTo(_spawnPosition.x + _velocity.x * elapsedTime, _spawnPosition.y + _velocity.y * elapsedTime);
            
            // ステージ外に出ていたら削除
            if (!Collision.hitTestCircleToRect(_currentPosition, 1, Temp.rectangle(0, 0, Const.STAGE_SIZE, Const.STAGE_SIZE))) {
                _exists = false; return;
            }
            
            // 相手チームのベースに入っていたら削除
            var teamBaseRect:Rectangle = (_team != Const.TEAM_RED)
                ? Temp.rectangle(0, 0, Const.TEAMBASE_SIZE, Const.TEAMBASE_SIZE)
                : Temp.rectangle(Const.STAGE_SIZE - Const.TEAMBASE_SIZE, Const.STAGE_SIZE - Const.TEAMBASE_SIZE, Const.TEAMBASE_SIZE, Const.TEAMBASE_SIZE);
            if (Collision.hitTestCircleToRect(_currentPosition, Const.BULLET_RADIUS, teamBaseRect)) {
                _exists = false; return;
            }
            
            // 敵の弾なら当たり判定
            if (_team != selfTeam) {
                var closestPoint:Point = Collision.getClosestPointLineToPoint(_previousPosition, _currentPosition, playerPos);
                if (Collision.hitTestCircleToCircle(playerPos, Const.TURRET_RADIUS, closestPoint, Const.BULLET_RADIUS)) {
                    _exists = false;
                    // sendMessageはPlayerクラスで行う
                    EventManager.instance.dispatchEvent(new HitEvent(closestPoint.x, closestPoint.y, _ownerID, _bulletID));
                }
            }
        }
        
        public function draw(camera:Camera, screen:BitmapData):void {
            // 画面外なら描画しない
            if (!Collision.hitTestCircleToRect(_currentPosition, Const.BULLET_RADIUS, camera.rect)) { return; }
            
            screen.copyPixels(
                Assets.images[(_team == Const.TEAM_RED) ? Const.IMAGE_RED_BULLET : Const.IMAGE_BLUE_BULLET][_imageIndex],
                Temp.rectangle(0, 0, 24, 24),
                Temp.point(_currentPosition.x - camera.rect.left - 12, _currentPosition.y - camera.rect.top - 12)
            );
        }
        
        public function get exists():Boolean { return _exists; }
    }
//}
//package ore.orelib.actors {
    import flash.display.BitmapData;
    import flash.geom.Point;
    import flash.utils.Dictionary;
    import net.user1.reactor.IClient;
    import net.user1.reactor.Room;
/*    import ore.orelib.commons.EventManager;
    import ore.orelib.commons.UPCConv;
    import ore.orelib.data.Const;
    import ore.orelib.events.HitEvent;
    import ore.orelib.events.ShootEvent;
    import ore.orelib.logic.Camera;
    import ore.orelib.logic.Protocol;
*/    
    //public 
    class BulletManager {
        private var _self:IClient;
        private var _room:Room;
        private var _bullets:Dictionary;
        private var _bulletPool:Vector.<Bullet>;
        private var _currentGameTime:int;
        
        public function BulletManager(self:IClient, room:Room) {
            _self = self;
            _room = room;
            _bullets = new Dictionary();
            _bulletPool = new Vector.<Bullet>();
            _currentGameTime = 0;
            
            EventManager.instance.addEventListener(ShootEvent.SHOOT, addSelfBullet);
            _room.addMessageListener(Const.MESSAGE_SHOOT, addOtherBullet);
            EventManager.instance.addEventListener(HitEvent.HIT, hitBulletToSelf);
            _room.addMessageListener(Const.MESSAGE_HIT, hitBulletToOther);
        }
        
        /** 自分の撃った弾を追加する */
        private function addSelfBullet(event:ShootEvent):void {
            addBullet(_self.getClientID(), event.uid, event.x, event.y, event.angle, event.spawnTime, _self.getAttribute(Const.ATTR_TEAM));
        }
        
        /** 他人の撃った弾を追加する */
        private function addOtherBullet(from:IClient, x_y:String, timestamp:String, angle_uid:String):void {
            var spawnTime:int = UPCConv.decode(timestamp);
            var elapsedTime:int = _currentGameTime - spawnTime;
            if (elapsedTime < -50 || 500 < elapsedTime) { return; }
            spawnTime = Math.min(Math.max(_currentGameTime - 100, spawnTime), _currentGameTime);
            var ix_y:int = UPCConv.decode(x_y);
            var iangle_uid:int = UPCConv.decode(angle_uid);
            addBullet(
                from.getClientID(),
                Protocol.decodeBulletUid(iangle_uid),
                Protocol.decodeX(ix_y),
                Protocol.decodeY(ix_y),
                Protocol.decodeBulletAngle(iangle_uid),
                spawnTime,
                from.getAttribute(Const.ATTR_TEAM)
            );
        }
        
        private function addBullet(ownerID:String, uid:int, x:int, y:int, angle:Number, spawnTime:int, team:String):void {
            var bullet:Bullet = (_bulletPool.length) ? _bulletPool.pop() : new Bullet();
            var bulletID:String = Protocol.getBulletId(ownerID, uid);
            bullet.init(ownerID, bulletID, x, y, angle, spawnTime, team);
            _bullets[bulletID] = bullet;
        }
        
        /** 自分に弾が当たった時の処理 */
        private function hitBulletToSelf(event:HitEvent):void {
            removeBullet(event.bulletID);
        }
        
        /** 他人に弾が当たった時の処理 */
        private function hitBulletToOther(from:IClient, x_y:String, bid:String):void {
            removeBullet(UPCConv.decode(bid).toString());
        }
        
        private function removeBullet(bulletID:String):void {
            if (!_bullets[bulletID]) { return; }
            _bulletPool.push(_bullets[bulletID]);
            delete _bullets[bulletID];
        }
        
        public function update(gameTime:int, playerPos:Point, selfTeam:String):void {
            _currentGameTime = gameTime;
            for (var bulletID:String in _bullets) {
                var bullet:Bullet = _bullets[bulletID];
                bullet.update(gameTime, playerPos, selfTeam);
                if (!bullet.exists) { removeBullet(bulletID); }
            }
        }
        
        public function draw(camera:Camera, screen:BitmapData):void {
            for each(var bullet:Bullet in _bullets) {
                bullet.draw(camera, screen);
            }
        }
        
        public function removeListeners():void {
            EventManager.instance.removeEventListener(ShootEvent.SHOOT, addSelfBullet);
            _room.removeMessageListener(Const.MESSAGE_SHOOT, addOtherBullet);
            EventManager.instance.removeEventListener(HitEvent.HIT, hitBulletToSelf);
            _room.removeMessageListener(Const.MESSAGE_HIT, hitBulletToOther);
        }
    }
//}
//package ore.orelib.actors {
    import flash.display.BitmapData;
    import flash.geom.Point;
/*    import ore.orelib.logic.Camera;
*/    
    //public 
    class AbstractEffect {
        protected var _position:Point;
        protected var _frameCount:int;
        
        public function AbstractEffect() {
            _position = new Point();
            _frameCount = 0;
        }
        
        public function init(x:int, y:int):void {
            _position.setTo(x, y);
            _frameCount = -1;
        }
        
        public function update():void {
            _frameCount++;
        }
        
        public function draw(camera:Camera, screen:BitmapData):void {
        }
        
        public function get exists():Boolean { return false; }
    }
//}
//package ore.orelib.actors {
    import flash.display.BitmapData;
/*    import ore.orelib.commons.Assets;
    import ore.orelib.commons.Temp;
    import ore.orelib.data.Const;
    import ore.orelib.logic.Camera;
    import ore.orelib.logic.Collision;
*/    
    //public 
    class HitEffect extends AbstractEffect {
        override public function draw(camera:Camera, screen:BitmapData):void {
            if (!Collision.hitTestCircleToRect(_position, 15, camera.rect)) { return; }
            
            var image:BitmapData = Assets.images[Const.IMAGE_HIT_EFFECT_ANIM][int(_frameCount / 2)];
            screen.copyPixels(image, Temp.rectangle(0, 0, 30, 30), Temp.point(_position.x - camera.rect.left - 15, _position.y - camera.rect.top - 15));
        }
        
        override public function get exists():Boolean { return _frameCount < 6; }
    }
//}
//package ore.orelib.actors {
    import flash.display.BitmapData;
/*    import ore.orelib.commons.Assets;
    import ore.orelib.commons.Temp;
    import ore.orelib.data.Const;
    import ore.orelib.logic.Camera;
    import ore.orelib.logic.Collision;
*/    
    //public 
    class KilledEffect extends AbstractEffect {
        override public function draw(camera:Camera, screen:BitmapData):void {
            if (!Collision.hitTestCircleToRect(_position, 120, camera.rect)) { return; }
            
            var image:BitmapData = Assets.images[Const.IMAGE_KILLED_EFFECT_ANIM][int(_frameCount / 2)];
            screen.copyPixels(image, Temp.rectangle(0, 0, 240, 240), Temp.point(_position.x - camera.rect.left - 120, _position.y - camera.rect.top - 120));
        }
        
        override public function get exists():Boolean { return _frameCount < 12; }
    }
//}
//package ore.orelib.actors {
    import flash.display.BitmapData;
    import net.user1.reactor.IClient;
    import net.user1.reactor.Room;
/*    import ore.orelib.commons.EventManager;
    import ore.orelib.commons.Temp;
    import ore.orelib.commons.UPCConv;
    import ore.orelib.data.Const;
    import ore.orelib.events.HitEvent;
    import ore.orelib.events.KilledEvent;
    import ore.orelib.logic.Camera;
    import ore.orelib.logic.Protocol;
*/    
    //public 
    class EffectManager {
        private var _room:Room;
        private var _hitEffects:Vector.<HitEffect>;
        private var _hitEffectPool:Vector.<HitEffect>;
        private var _killedEffects:Vector.<KilledEffect>;
        private var _killedEffectPool:Vector.<KilledEffect>;
        private var _redoutCount:int;
        
        private static const REDOUT_DURATION:int = 4;
        
        public function EffectManager(room:Room) {
            _room = room;
            _hitEffects = new Vector.<HitEffect>();
            _hitEffectPool = new Vector.<HitEffect>();
            _killedEffects = new Vector.<KilledEffect>();
            _killedEffectPool = new Vector.<KilledEffect>();
            _redoutCount = 0;
            
            EventManager.instance.addEventListener(HitEvent.HIT, hitBulletToSelf);
            _room.addMessageListener(Const.MESSAGE_HIT, hitBulletToOther);
            EventManager.instance.addEventListener(KilledEvent.KILLED, onSelfKilled);
            _room.addMessageListener(Const.MESSAGE_KILLED, onOtherKilled);
        }
        
        private function hitBulletToSelf(event:HitEvent):void {
            addHitEffect(event.x, event.y);
            _redoutCount = REDOUT_DURATION;
        }
        
        private function hitBulletToOther(from:IClient, x_y:String, bid:String):void {
            var ix_y:int = UPCConv.decode(x_y);
            addHitEffect(Protocol.decodeX(ix_y), Protocol.decodeY(ix_y));
        }
        
        private function addHitEffect(x:int, y:int):void {
            var hitEffect:HitEffect = (_hitEffectPool.length) ? _hitEffectPool.pop() : new HitEffect();
            hitEffect.init(x, y);
            _hitEffects.push(hitEffect);
        }
        
        private function onSelfKilled(event:KilledEvent):void {
            addKilledEffect(event.x, event.y);
            _redoutCount = REDOUT_DURATION;
        }
        
        private function onOtherKilled(from:IClient, x_y:String, killerID:String):void {
            var ix_y:int = UPCConv.decode(x_y);
            addKilledEffect(Protocol.decodeX(ix_y), Protocol.decodeY(ix_y));
        }
        
        private function addKilledEffect(x:int, y:int):void {
            var killedEffect:KilledEffect = (_killedEffectPool.length) ? _killedEffectPool.pop() : new KilledEffect();
            killedEffect.init(x, y);
            _killedEffects.push(killedEffect);
        }
        
        public function update():void {
            for (var i:int = _hitEffects.length - 1; i >= 0; i--) {
                var hitEffect:HitEffect = _hitEffects[i];
                hitEffect.update();
                if (!hitEffect.exists) {
                    _hitEffects.splice(i, 1);
                    _hitEffectPool.push(hitEffect);
                }
            }
            for (var j:int = _killedEffects.length - 1; j >= 0; j--) {
                var killedEffect:KilledEffect = _killedEffects[j];
                killedEffect.update();
                if (!killedEffect.exists) {
                    _killedEffects.splice(j, 1);
                    _killedEffectPool.push(killedEffect);
                }
            }
        }
        
        public function draw(camera:Camera, screen:BitmapData):void {
            for each(var hitEffect:HitEffect in _hitEffects) {
                hitEffect.draw(camera, screen);
            }
            for each(var killedEffect:KilledEffect in _killedEffects) {
                killedEffect.draw(camera, screen);
            }
            if (_redoutCount-- > 0) {
                screen.colorTransform(Temp.rectangle(0, 0, 465, 465), Temp.colorTransform(1, 1, 1, 1, 32 * _redoutCount));
            }
        }
        
        public function removeListeners():void {
            EventManager.instance.removeEventListener(HitEvent.HIT, hitBulletToSelf);
            _room.removeMessageListener(Const.MESSAGE_HIT, hitBulletToOther);
            EventManager.instance.removeEventListener(KilledEvent.KILLED, onSelfKilled);
            _room.removeMessageListener(Const.MESSAGE_KILLED, onOtherKilled);
        }
    }
//}
//package ore.orelib.events {
    import flash.events.Event;
    
    //public 
    class ShootEvent extends Event {
        private var _x:int;
        private var _y:int;
        private var _angle:Number;
        private var _spawnTime:int;
        private var _uid:int;
        
        public static const SHOOT:String = "shoot";
        
        public function ShootEvent(x:int, y:int, angle:Number, spawnTime:int, uid:int) {
            super(ShootEvent.SHOOT);
            _x = x; _y = y; _angle = angle; _spawnTime = spawnTime; _uid = uid;
        }
        
        public override function clone():Event { return new ShootEvent(_x, _y, _angle, _spawnTime, _uid); }
        public override function toString():String { return formatToString("ShootEvent", "x", "y", "angle", "spawnTime", "uid"); }
        
        public function get x():int { return _x; }
        public function get y():int { return _y; }
        public function get angle():Number { return _angle; }
        public function get spawnTime():int { return _spawnTime; }
        public function get uid():int { return _uid; }
    }
//}
//package ore.orelib.events {
    import flash.events.Event;
    
    //public 
    class HitEvent extends Event {
        private var _x:int;
        private var _y:int;
        private var _ownerID:String;
        private var _bulletID:String;
        
        public static const HIT:String = "hit";
        
        public function HitEvent(x:int, y:int, ownerID:String, bulletID:String) {
            super(HitEvent.HIT);
            _x = x; _y = y; _ownerID = ownerID; _bulletID = bulletID;
        }
        
        public override function clone():Event { return new HitEvent(_x, _y, _ownerID, _bulletID); }
        public override function toString():String { return formatToString("HitEvent", "x", "y", "ownerID", "bulletID"); }
        
        public function get x():int { return _x; }
        public function get y():int { return _y; }
        public function get ownerID():String { return _ownerID; }
        public function get bulletID():String { return _bulletID; }
    }
//}
//package ore.orelib.events {
    import flash.events.Event;
    
    //public 
    class KilledEvent extends Event {
        private var _x:int;
        private var _y:int;
        private var _selfID:String;
        private var _nemesisID:String;
        
        public static const KILLED:String = "killed";
        
        public function KilledEvent(x:int, y:int, selfID:String, nemesisID:String) {
            super(KilledEvent.KILLED);
            _x = x; _y = y; _selfID = selfID; _nemesisID = nemesisID;
        }
        
        public override function clone():Event { return new KilledEvent(_x, _y, _selfID, _nemesisID); }
        public override function toString():String { return formatToString("KilledEvent", "x", "y", "selfID", "nemesisID"); }
        
        public function get x():int { return _x; }
        public function get y():int { return _y; }
        public function get selfID():String { return _selfID; }
        public function get nemesisID():String { return _nemesisID; }
    }
//}
//package ore.orelib.events {
    import flash.events.Event;
    
    //public 
    class CaptureEvent extends Event {
        public static const CAPTURE:String = "capture";
        
        public function CaptureEvent() {
            super(CaptureEvent.CAPTURE);
        }
        
        public override function clone():Event { return new CaptureEvent(); }
        public override function toString():String { return formatToString("CaptureEvent"); }
    }
//}
//package ore.orelib.assets {
    import flash.display.BitmapData;
    import flash.display.BitmapDataChannel;
    import flash.display.GradientType;
    import flash.display.Graphics;
    import flash.display.GraphicsGradientFill;
    import flash.display.IGraphicsData;
    import flash.display.Sprite;
    import flash.filters.DisplacementMapFilter;
    import flash.filters.DisplacementMapFilterMode;
    import flash.filters.GlowFilter;
    import flash.geom.Matrix;
    import flash.geom.Point;
    
    //public 
    class Artist {
        public static function createTurrets(color:uint):Vector.<BitmapData> {
            var result:Vector.<BitmapData> = new Vector.<BitmapData>();
            for (var i:int = 0; i < 72; i++) {
                result[i] = createTurret(color, i * 5 * Math.PI / 180);
            }
            return result;
        }
        
        private static function createTurret(color:uint, angle:Number):BitmapData {
            var result:BitmapData = new BitmapData(64, 64, true, 0x00FFFFFF);
            var sp:Sprite = new Sprite();
            var g:Graphics = sp.graphics;
            g.lineStyle(2, 0xFFFFFF, 1, false, "normal", "square", "miter");
            g.beginFill(color); g.drawRect(2, 28, 30, 8); g.endFill();
            g.beginFill(color); g.drawCircle(32, 32, 16); g.endFill();
            var matrix:Matrix = new Matrix(1, 0, 0, 1, -32, -32);
            matrix.rotate(angle);
            matrix.translate(32, 32);
            result.draw(sp, matrix, null, null, null, true);
            return result;
        }
        
        public static function createBullets(color:uint):Vector.<BitmapData> {
            var result:Vector.<BitmapData> = new Vector.<BitmapData>();
            for (var i:int = 0; i < 36; i++) {
                result[i] = createBullet(color, i * 5 * Math.PI / 180);
            }
            return result;
        }
        
        private static function createBullet(color:uint, angle:Number):BitmapData {
            var result:BitmapData = new BitmapData(24, 24, true, 0x00FFFFFF);
            var sp:Sprite = new Sprite();
            var g:Graphics = sp.graphics;
            g.beginFill(0xFFFFFF); g.drawRoundRect(4, 8, 16, 8, 8); g.endFill();
            sp.filters = [new GlowFilter(color, 1, 8, 8)];
            var matrix:Matrix = new Matrix(1, 0, 0, 1, -12, -12);
            matrix.rotate(angle);
            matrix.translate(12, 12);
            result.draw(sp, matrix, null, null, null, true);
            return result;
        }
        
        public static function createIndicator():BitmapData {
            var result:BitmapData = new BitmapData(30, 20, true, 0x00FFFFFF);
            var sp:Sprite = new Sprite();
            var g:Graphics = sp.graphics;
            g.beginFill(0xFFFFFF); g.lineTo(30, 10); g.lineTo(0, 20); g.curveTo(5, 10, 0, 0); g.endFill();
            result.draw(sp);
            return result;
        }
        
        public static function createBackground(arenaSize:int, teambaseSize:int, controlPointRadius:int):BitmapData {
            var result:BitmapData = new BitmapData(arenaSize, arenaSize, false, 0x000000);
            var sp:Sprite = new Sprite();
            var g:Graphics = sp.graphics;
            // grid
            g.lineStyle(2, 0x004400, 1, true, "normal", "none", "bevel");
            for (var x:int = 0; x <= arenaSize; x += 100) { g.moveTo(x, 0); g.lineTo(x, arenaSize); }
            for (var y:int = 0; y <= arenaSize; y += 100) { g.moveTo(0, y); g.lineTo(arenaSize, y); }
            g.lineStyle();
            // red
            g.beginFill(0x440000, 0.5); g.drawRect(0, 0, teambaseSize, teambaseSize); g.endFill();
            // blue
            g.beginFill(0x000044, 0.5); g.drawRect(arenaSize - teambaseSize, arenaSize - teambaseSize, teambaseSize, teambaseSize); g.endFill();
            // controlpoint
            var matrix:Matrix = new Matrix();
            matrix.createGradientBox(controlPointRadius * 2, controlPointRadius * 2, 0, arenaSize / 2 - controlPointRadius, arenaSize / 2 - controlPointRadius);
            g.beginGradientFill("radial", [0x888888, 0x444444], [1, 1], [64, 255], matrix);
            g.drawCircle(arenaSize / 2, arenaSize / 2, controlPointRadius); g.endFill();
            result.draw(sp);
            return result;
        }
        
        public static function createHitEffectAnimation():Vector.<BitmapData> {
            var result:Vector.<BitmapData> = new Vector.<BitmapData>(3, true);
            var sp:Sprite = new Sprite();
            var g:Graphics = sp.graphics;
            // frame0
            g.clear(); g.beginFill(0xFFFFFF); g.drawCircle(15, 15, 9); g.endFill();
            result[0] = createImageAppliedPerlinNoiseDisplacementMapFilter(sp, 30, 0, 0);
            // frame1
            g.clear(); g.beginFill(0xFFFFFF); g.drawCircle(15, 15, 12); g.drawCircle(15, 15, 6); g.endFill();
            result[1] = createImageAppliedPerlinNoiseDisplacementMapFilter(sp, 30, 1, 0);
            // frame2
            g.clear(); g.beginFill(0xFFFFFF); g.drawCircle(15, 15, 15); g.drawCircle(15, 15, 12); g.endFill();
            result[2] = createImageAppliedPerlinNoiseDisplacementMapFilter(sp, 30, 1, 0);
            return result;
        }
        
        public static function createKilledEffectAnimation():Vector.<BitmapData> {
            var result:Vector.<BitmapData> = new Vector.<BitmapData>(6, true);
            var sp:Sprite = new Sprite();
            var g:Graphics = sp.graphics;
            var matrix:Matrix = new Matrix();
            matrix.createGradientBox(160, 160, 0, 40, 40);
            var explosionGradient:Vector.<IGraphicsData> = new <IGraphicsData>[
                new GraphicsGradientFill(GradientType.RADIAL, [0xFFFFFF, 0xFFFF88, 0xFF8844, 0xCC4444, 0x000000], [1, 1, 1, 1, 0], [0, 96, 160, 192, 255], matrix)
            ];
            var smokeGradient:Vector.<IGraphicsData> = new <IGraphicsData>[
                new GraphicsGradientFill(GradientType.RADIAL, [0xFFFFFF, 0xCCCCCC], [0.6, 0.1], [0, 255], matrix)
            ];
            // frame0/
            g.clear(); g.drawGraphicsData(explosionGradient); g.drawCircle(120, 120, 30); g.endFill();
            result[0] = createImageAppliedPerlinNoiseDisplacementMapFilter(sp, 20, 0, 20);
            // frame1
            g.clear(); g.drawGraphicsData(explosionGradient); g.drawCircle(120, 120, 50); g.endFill();
            result[1] = createImageAppliedPerlinNoiseDisplacementMapFilter(sp, 20, 1, 50);
            // frame2
            g.clear();
            g.drawGraphicsData(smokeGradient); g.drawCircle(120, 120, 70); g.endFill();
            g.drawGraphicsData(explosionGradient); g.drawCircle(120, 120, 60); g.endFill();
            result[2] = createImageAppliedPerlinNoiseDisplacementMapFilter(sp, 10, 2, 60);
            // frame3
            g.clear(); g.drawGraphicsData(smokeGradient); g.drawCircle(120, 120, 80); g.drawCircle(120, 120, 10); g.endFill();
            g.beginGradientFill(GradientType.RADIAL, [0xFFFF88, 0xFF8844, 0xCC4444, 0x000000], [0.8, 0.8, 0.8, 0], [64, 128, 160, 255], matrix);
            g.drawCircle(120, 120, 60); g.drawCircle(120, 120, 10); g.endFill();
            result[3] = createImageAppliedPerlinNoiseDisplacementMapFilter(sp, 10, 3, 60);
            // frame4
            g.clear(); g.drawGraphicsData(smokeGradient); g.drawCircle(80, 80, 40); g.drawCircle(160, 80, 40); g.drawCircle(80, 160, 40); g.drawCircle(160, 160, 40); g.endFill();
            g.beginGradientFill(GradientType.RADIAL, [0xFFFF88, 0xFF8844, 0xCC4444, 0x000000], [0.6, 0.6, 0.6, 0], [32, 96, 128, 255], matrix);
            g.drawCircle(120, 120, 60); g.drawCircle(120, 120, 20); g.endFill();
            result[4] = createImageAppliedPerlinNoiseDisplacementMapFilter(sp, 8, 4, 80);
            // frame5
            g.clear(); g.drawGraphicsData(smokeGradient); g.drawRoundRect(40, 40, 160, 160, 80); g.drawCircle(120, 120, 60); g.endFill();
            result[5] = createImageAppliedPerlinNoiseDisplacementMapFilter(sp, 6, 5, 80);
            return result;
        }
        
        public static function createImageAppliedPerlinNoiseDisplacementMapFilter(sp:Sprite, base:int, seed:int, scale:int):BitmapData {
            var result:BitmapData = new BitmapData(240, 240, true, 0x00FFFFFF);
            var noise:BitmapData = result.clone();
            noise.perlinNoise(base, base, 8, seed, false, true, BitmapDataChannel.RED | BitmapDataChannel.GREEN);
            result.draw(sp);
            result.applyFilter(result, result.rect, new Point(), new DisplacementMapFilter(
                noise, new Point(), BitmapDataChannel.RED, BitmapDataChannel.GREEN,
                scale, scale, DisplacementMapFilterMode.CLAMP
            ));
            return result;
        }
    }
//}
//package ore.orelib.assets {
    import com.bit101.components.PushButton;
    import flash.display.Loader;
    import flash.display.Sprite;
/*    import flash.events.MouseEvent;
    import ore.orelib.commons.Assets;
    import ore.orelib.commons.Labeler;
    import ore.orelib.data.Const;
*/    
    //public 
    class InstructionWindow extends Sprite {
        public function InstructionWindow() {
            graphics.beginFill(0x000000, 0.8);
            graphics.drawRect(0, 0, 465, 465);
            graphics.endFill();
            
            addChild(
                new Labeler().align(Labeler.CENTER)
                .font(Const.FONT).fontColor(0xFFFFFF).fontSize(14)
                .selectable().wordWrap()
                .pos(25, 130).size(415, 265).build(""
                    //+ "Kill opponents and capture the central control point to gain score.\n"
                    //+ "The winner is the team with the higher score at the end of the game.\n\n"
                    + "敵を倒したり、中央地点を占領したりしてスコアを稼げ!\n"
                    + "ゲーム終了時にスコアが多い方のチームが勝ちだ!\n\n"
                    + "敵を倒すと10点\n中央地点は5秒ごとに3点+HP回復\n"
                )
            );
            var controls:Loader = Assets.images[Const.IMAGE_LOADER_CONTROLS];
            controls.x = 132; controls.y = 220;
            addChild(controls);
            addChild(
                new Labeler().autoSize(Labeler.CENTER)
                .font(Const.FONT).fontColor(0xFFFFFF).fontSize(14)
                .selectable().pos(25, 300).size(415, 100).build(""
                    + "Space : スコア表示\n"
                    + "Esc : タイトルに戻る\n"
                    //+ "Space : show scoreboard (スコア表示)\n"
                    //+ "Esc : back to title (タイトルに戻る)\n"
                )
            );
            new PushButton(this, 182, 380, "OK", close);
        }
        
        private function close(event:MouseEvent):void {
            parent.removeChild(this);
        }
    }
//}
//package ore.orelib.assets {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Sprite;
    import flash.events.TimerEvent;
    import flash.text.TextField;
    import flash.utils.Timer;
    import net.user1.reactor.Reactor;
    import net.user1.reactor.Room;
    import net.user1.reactor.RoomEvent;
    import net.user1.reactor.RoomSettings;
    import net.wonderfl.utils.WonderflAPI;
/*    import ore.orelib.commons.Labeler;
    import ore.orelib.data.Const;
*/    
    //public 
    class ScoreBoard extends Sprite {
        private var _reactor:Reactor;
        private var _api:WonderflAPI;
        private var _room:Room;
        private var _updateTimer:Timer;
        // データ関連
        private var _items:Vector.<ScoreBoardItem>;
        private var _itemPool:Vector.<ScoreBoardItem>;
        private var _numRedPlayers:int;
        private var _numBluePlayers:int;
        private var _redTeamScore:int;
        private var _blueTeamScore:int;
        private var _lockedScore:Boolean;
        // 表示関連
        private var _numRedPlayersLabel:TextField;
        private var _redTeamScoreLabel:TextField;
        private var _numBluePlayersLabel:TextField;
        private var _blueTeamScoreLabel:TextField;
        private var _redNameLabel:TextField;
        private var _redScoreLabel:TextField;
        private var _blueNameLabel:TextField;
        private var _blueScoreLabel:TextField;
        
        public function ScoreBoard(reactor:Reactor, api:WonderflAPI) {
            _reactor = reactor;
            _api = api;
            
            // 名前・スコア・所属チームのみの通信を行うを部屋を作成する
            var roomSettings:RoomSettings = new RoomSettings();
            roomSettings.password = String(_api.apiKey);
            roomSettings.removeOnEmpty = false;
            _room = _reactor.getRoomManager().createRoom(String(_api.appID) + ".s", roomSettings);
            _room.addEventListener(RoomEvent.ADD_OCCUPANT, addOccupantHandler);
            _room.addEventListener(RoomEvent.REMOVE_OCCUPANT, removeOccupantHandler);
            _room.observe(String(_api.apiKey));
            
            _updateTimer = new Timer(1000);
            _updateTimer.addEventListener(TimerEvent.TIMER, onTimer);
            _updateTimer.start();
            
            _items = new Vector.<ScoreBoardItem>();
            _itemPool = new Vector.<ScoreBoardItem>();
            _numRedPlayers = _numBluePlayers = _redTeamScore = _blueTeamScore = 0;
            _lockedScore = false;
            
            this.x = 10; this.y = 110;
            addChild(new Bitmap(createBackground()));
            var labelerL:Labeler = new Labeler().font(Const.FONT, -400, 400).fontSize(20).size(200, 25);
            addChild(_numRedPlayersLabel = labelerL.align(Labeler.LEFT).fontColor(Const.COLOR_RED).pos(10, 10).build("Red (0)"));
            addChild(_redTeamScoreLabel = labelerL.align(Labeler.RIGHT).fontColor(Const.COLOR_RED).pos(10, 10).build("0"));
            addChild(_numBluePlayersLabel = labelerL.align(Labeler.LEFT).fontColor(Const.COLOR_BLUE).pos(235, 10).build("Blue (0)"));
            addChild(_blueTeamScoreLabel = labelerL.align(Labeler.RIGHT).fontColor(Const.COLOR_BLUE).pos(235, 10).build("0"));
            var labelerS:Labeler = new Labeler().font(Const.FONT, -400, 400).fontSize(12).size(190, 285);
            addChild(_redNameLabel = labelerS.align(Labeler.LEFT).fontColor(Const.COLOR_RED).pos(15, 40).build(""));
            addChild(_redScoreLabel = labelerS.align(Labeler.RIGHT).fontColor(Const.COLOR_RED).pos(15, 40).build(""));
            addChild(_blueNameLabel = labelerS.align(Labeler.LEFT).fontColor(Const.COLOR_BLUE).pos(235, 40).build(""));
            addChild(_blueScoreLabel = labelerS.align(Labeler.RIGHT).fontColor(Const.COLOR_BLUE).pos(235, 40).build(""));
        }
        
        private function createBackground():BitmapData {
            var result:BitmapData = new BitmapData(445, 325, true, 0x00FFFFFF);
            var sp:Sprite = new Sprite();
            var g:Graphics = sp.graphics;
            g.beginFill(0x444444, 0.8); g.drawRoundRect(0, 0, 445, 325, 20); g.endFill();
            g.lineStyle(2, Const.COLOR_RED, 1, true, "normal", "none", "bevel"); g.moveTo(10, 35); g.lineTo(210, 35);
            g.lineStyle(2, Const.COLOR_BLUE, 1, true, "normal", "none", "bevel"); g.moveTo(235, 35); g.lineTo(435, 35);
            result.draw(sp);
            return result;
        }
        
        private function addOccupantHandler(event:RoomEvent):void {
            var item:ScoreBoardItem = (_itemPool.length) ? _itemPool.pop() : new ScoreBoardItem();
            item.init(event.getClient());
            _items.push(item);
        }
        
        private function removeOccupantHandler(event:RoomEvent):void {
            for (var i:int = _items.length - 1; i >= 0; i--) {
                var item:ScoreBoardItem = _items[i];
                if (item.clientID == event.getClientID()) {
                    _items.splice(i, 1);
                    _itemPool.push(item);
                    break;
                }
            }
        }
        
        public function register():void { _room.join(String(_api.apiKey)); }
        public function unregister():void { if (_room.clientIsInRoom()) { _room.leave(); }}
        
        private function onTimer(event:TimerEvent = null):void {
            // 現在のスコアに更新してソート
            for each(var item:ScoreBoardItem in _items) {
                item.update(_room.getClient(item.clientID));
            }
            _items.sort(compareScore);
            
            // 表示に反映
            var redNameText:String = "";
            var redScoreText:String = "";
            var blueNameText:String = "";
            var blueScoreText:String = "";
            _numRedPlayers = _numBluePlayers = 0;
            if (!_lockedScore) {
                _redTeamScore = _blueTeamScore = 0;
            }
            for (var i:int = _items.length - 1; i >= 0; i--) {
                item = _items[i];
                if (item.team == Const.TEAM_RED) {
                    redNameText += item.name + "\n";
                    redScoreText += item.score + "\n";
                    _numRedPlayers++;
                    if (!_lockedScore) { _redTeamScore += item.score; }
                } else {
                    blueNameText += item.name + "\n";
                    blueScoreText += item.score + "\n";
                    _numBluePlayers++;
                    if (!_lockedScore) { _blueTeamScore += item.score; }
                }
            }
            _numRedPlayersLabel.text = "Red (" + _numRedPlayers + ")";
            _redTeamScoreLabel.text = _redTeamScore.toString();
            _numBluePlayersLabel.text = "Blue (" + _numBluePlayers + ")";
            _blueTeamScoreLabel.text = _blueTeamScore.toString();
            _redNameLabel.text = redNameText;
            _redScoreLabel.text = redScoreText;
            _blueNameLabel.text = blueNameText;
            _blueScoreLabel.text = blueScoreText;
        }
        
        private function compareScore(a:ScoreBoardItem, b:ScoreBoardItem):Number {
            var diff:int = a.score - b.score; // scoreが小さい順に並べる
            return (diff != 0) ? diff : int(b.clientID) - int(a.clientID); // scoreが同じなら、IDが大きい順に並べる
        }
        
        public function update(gameTime:int):void {
            _lockedScore = (gameTime < Const.SETUP_DURATION);
        }
        
        public function get numRedPlayers():int { return _numRedPlayers; }
        public function get numBluePlayers():int { return _numBluePlayers; }
        public function get redTeamScore():int { return _redTeamScore; }
        public function get blueTeamScore():int { return _blueTeamScore; }
    }
//}
//package ore.orelib.assets {
    import net.user1.reactor.IClient;
/*    import ore.orelib.data.Const;
*/    
    //public 
    class ScoreBoardItem {
        private var _clientID:String;
        private var _name:String;
        private var _score:int;
        private var _team:String;
        
        public function ScoreBoardItem() {
            _clientID = _name = "";
            _score = 0;
            _team = "";
        }
        
        public function init(client:IClient):void {
            _clientID = client.getClientID();
            _name = client.getAttribute(Const.ATTR_NAME);
            _score = int(client.getAttribute(Const.ATTR_SCORE));
            _team = client.getAttribute(Const.ATTR_TEAM);
        }
        
        public function update(client:IClient):void {
            if (!client) { return; }
            var score:int = int(client.getAttribute(Const.ATTR_SCORE));
            if (_score != score && _team == client.getAttribute(Const.ATTR_TEAM)) {
                _score = score;
            }
        }
        
        public function get clientID():String { return _clientID; }
        public function get name():String { return _name; }
        public function get score():int { return _score; }
        public function get team():String { return _team; }
    }
//}
//package ore.orelib.assets {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.filters.GlowFilter;
    import flash.text.TextField;
    import net.user1.reactor.IClient;
    import net.user1.reactor.Room;
    import net.user1.reactor.RoomEvent;
/*    import ore.orelib.commons.EventManager;
    import ore.orelib.commons.Labeler;
    import ore.orelib.commons.Temp;
    import ore.orelib.data.Const;
    import ore.orelib.events.CaptureEvent;
    import ore.orelib.events.KilledEvent;
    import ore.orelib.logic.ControlPoint;
    import ore.orelib.logic.Player;
*/    
    //public 
    class HUD extends Sprite {
        private var _self:IClient;
        private var _room:Room;
        private var _player:Player;
        private var _controlPoint:ControlPoint;
        // 表示関連
        private var _timeLabel:TextField;
        private var _actionGaugeContainer:Sprite;
        private var _actionGauge:BitmapData;
        private var _actionGaugeLabel:TextField;
        private var _logLabels:Vector.<TextField>;
        private var _teamScoreGauge:BitmapData;
        
        private static const LOG_SIZE:int = 5;
        private static const COLOR_SCORED:uint = 0xFFFF44;
        
        public function HUD(self:IClient, room:Room, player:Player, controlPoint:ControlPoint) {
            _self = self;
            _room = room;
            _player = player;
            _controlPoint = controlPoint;
            
            addChild(_timeLabel = new Labeler().autoSize(Labeler.LEFT)
                .filters([new GlowFilter(0x000000, 1, 2, 2)])
                .font(Const.FONT, -400, 400).fontColor(0xFFFFFF).fontSize(20)
                .pos(10, 10).size(100, 20).build("0:00")
            );
            
            addChild(_actionGaugeContainer = createActionGaugeContainer());
            _actionGaugeContainer.addChild(createActionGaugeBitmap(_actionGauge = new BitmapData(102, 20, false, 0xFFFFFF)));
            _actionGaugeContainer.addChild(_actionGaugeLabel = new Labeler().align(Labeler.CENTER).autoSize(Labeler.NONE, Labeler.MIDDLE)
                .filters([new GlowFilter(0x000000, 1, 2, 2)])
                .font(Const.FONT, -400, 400).fontColor(0xFFFFFF).fontSize(14)
                .pos(0, 0).size(102, 20).build("")
            );
            
            _logLabels = new Vector.<TextField>();
            var logLabeler:Labeler = new Labeler().autoSize(Labeler.NONE, Labeler.MIDDLE)
                .filters([new GlowFilter(0x000000, 1, 2, 2)])
                .font(Const.FONT, -400, 400).fontColor(0xFFFFFF).fontSize(9).size(445, 12);
            for (var i:int = 0; i < LOG_SIZE; i++) {
                addChild(_logLabels[i] = logLabeler.pos(10, 435 - 12 * (LOG_SIZE - i)).build(""));
            }
            
            var teamScoreGaugeBitmap:Bitmap = new Bitmap(_teamScoreGauge = new BitmapData(445, 10, false, 0x000000));
            teamScoreGaugeBitmap.x = 10; teamScoreGaugeBitmap.y = 445; teamScoreGaugeBitmap.alpha = 0.5;
            addChild(teamScoreGaugeBitmap);
            
            _room.addEventListener(RoomEvent.ADD_OCCUPANT, addOccupantHandler);
            _room.addEventListener(RoomEvent.REMOVE_OCCUPANT, removeOccupantHandler);
            EventManager.instance.addEventListener(KilledEvent.KILLED, onSelfKilled);
            _room.addMessageListener(Const.MESSAGE_KILLED, onOtherKilled);
            EventManager.instance.addEventListener(CaptureEvent.CAPTURE, onCaptureControlPoint);
        }
        
        private function createActionGaugeContainer():Sprite {
            var result:Sprite = new Sprite();
            result.x = 181; result.y = 222;
            result.mouseEnabled = false;
            result.visible = false;
            return result;
        }
        
        private function createActionGaugeBitmap(bitmapData:BitmapData):Bitmap {
            var result:Bitmap = new Bitmap(bitmapData);
            result.alpha = 0.5;
            return result;
        }
        
        private function addOccupantHandler(event:RoomEvent):void {
            // 自分が参加した時、その前から既に参加しているプレイヤーは表示しない
            if (_room.clientIsInRoom()) {
                var team:String = (event.getClient().getAttribute(Const.ATTR_TEAM) == Const.TEAM_RED) ? "Red" : "Blue";
                addLog(event.getClient().getAttribute(Const.ATTR_NAME) + " joined the " + team + " team.", 0xFFFFFF);
            }
        }
        
        private function removeOccupantHandler(event:RoomEvent):void {
            var team:String = (event.getClient().getAttribute(Const.ATTR_TEAM) == Const.TEAM_RED) ? "Red" : "Blue";
            addLog(event.getClient().getAttribute(Const.ATTR_NAME) + " left the " + team + " team.", 0xFFFFFF);
        }
        
        private function onSelfKilled(event:KilledEvent):void {
            var killer:IClient = _room.getClient(event.nemesisID);
            var killerName:String = (killer) ? killer.getAttribute(Const.ATTR_NAME) : "";
            var color:uint;
            if (killer) {
                color = (killer.getAttribute(Const.ATTR_TEAM) == Const.TEAM_RED) ? Const.COLOR_RED : Const.COLOR_BLUE;
            } else {
                color = (_self.getAttribute(Const.ATTR_TEAM) != Const.TEAM_RED) ? Const.COLOR_RED : Const.COLOR_BLUE;
            }
            addLog(killerName + " -> " + _self.getAttribute(Const.ATTR_NAME), color);
        }
        
        private function onOtherKilled(from:IClient, x_y:String, killerID:String):void {
            var killer:IClient = _room.getClient(killerID);
            var killerName:String = (killer) ? killer.getAttribute(Const.ATTR_NAME) : "";
            var killedName:String = from.getAttribute(Const.ATTR_NAME);
            var color:uint;
            if (!killer) {
                color = (from.getAttribute(Const.ATTR_TEAM) != Const.TEAM_RED) ? Const.COLOR_RED : Const.COLOR_BLUE;
            } else if (killer.isSelf()) {
                color = COLOR_SCORED;
            } else if (killer.getAttribute(Const.ATTR_TEAM) == Const.TEAM_RED) {
                color = Const.COLOR_RED;
            } else {
                color = Const.COLOR_BLUE;
            }
            addLog(killerName + " -> " + killedName, color);
        }
        
        private function onCaptureControlPoint(event:CaptureEvent):void {
            addLog(_self.getAttribute(Const.ATTR_NAME) + " +1", COLOR_SCORED);
        }
        
        private function addLog(text:String, color:uint):void {
            for (var i:int = 1; i < LOG_SIZE; i++) {
                var log1:TextField = _logLabels[int(i - 1)];
                var log2:TextField = _logLabels[i];
                log1.text = log2.text;
                log1.textColor = log2.textColor;
            }
            // log2は最後のログ
            log2.text = text;
            log2.textColor = color;
        }
        
        public function update(gameTime:int, redScore:int, blueScore:int):void {
            // ゲーム時間表示
            var currentTime:int, timeLabelColor:uint;
            if (gameTime < Const.SETUP_DURATION) {
                currentTime = (Const.SETUP_DURATION - gameTime) / 1000;
                timeLabelColor = 0xFFFF88;
            } else {
                currentTime = (Const.GAME_DURATION - gameTime) / 1000;
                timeLabelColor = (gameTime < Const.GAME_DURATION - 30000) ? 0xFFFFFF : 0xFF8888;
            }
            _timeLabel.text = int(currentTime / 60) + ":" + ("00" + int(currentTime % 60)).substr(-2);
            _timeLabel.textColor = timeLabelColor;
            
            // アクションゲージ
            if (_player.respawnRate < 1) {
                _actionGaugeContainer.visible = true;
                _actionGauge.fillRect(Temp.rectangle(1, 1, 100, 18), 0x444444);
                _actionGauge.fillRect(Temp.rectangle(1, 1, 100 * _player.respawnRate, 18), 0xCCCCCC);
                _actionGaugeLabel.text = "Respawning...";
            } else if (_controlPoint.captureRate > 0) {
                _actionGaugeContainer.visible = true;
                _actionGauge.fillRect(Temp.rectangle(1, 1, 100, 18), 0x444444);
                _actionGauge.fillRect(Temp.rectangle(1, 1, 100 * _controlPoint.captureRate, 18), 0xCCCCCC);
                _actionGaugeLabel.text = "Capturing...";
            } else {
                _actionGaugeContainer.visible = false;
            }
            
            // スコアゲージ
            _teamScoreGauge.fillRect(Temp.rectangle(0, 0, 445, 10), 0x0000FF);
            _teamScoreGauge.fillRect(Temp.rectangle(0, 0, Math.min(Math.max(0, 222 + (redScore - blueScore) * 2), 445), 10), 0xFF0000);
            _teamScoreGauge.fillRect(Temp.rectangle(222, 0, 1, 10), 0xFFFF00);
        }
        
        public function removeListeners():void {
            _room.removeEventListener(RoomEvent.ADD_OCCUPANT, addOccupantHandler);
            _room.removeEventListener(RoomEvent.REMOVE_OCCUPANT, removeOccupantHandler);
            EventManager.instance.removeEventListener(KilledEvent.KILLED, onSelfKilled);
            _room.removeMessageListener(Const.MESSAGE_KILLED, onOtherKilled);
            EventManager.instance.addEventListener(CaptureEvent.CAPTURE, onCaptureControlPoint);
        }
    }
//}
//package ore.orelib.commons {
    import flash.utils.Dictionary;
    
    //public 
    class Assets {
        public static var images:Dictionary = new Dictionary();
    }
//}
//package ore.orelib.commons {
    import com.bit101.components.PushButton;
    import com.bit101.components.VScrollBar;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.FocusEvent;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.filters.BevelFilter;
    import flash.filters.DropShadowFilter;
    import flash.geom.Point;
    import flash.system.Capabilities;
    import flash.system.IME;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFieldType;
    import flash.text.TextFormat;
    import flash.text.TextFormatAlign;
    import flash.ui.Keyboard;
    import flash.utils.getTimer;
    import flash.utils.Timer;
    import net.user1.reactor.filters.IFilter;
    import net.user1.reactor.IClient;
    import net.user1.reactor.Reactor;
    import net.user1.reactor.ReactorEvent;
    import net.user1.reactor.Room;
    import net.user1.reactor.RoomEvent;
    import net.user1.reactor.UpdateLevels;
    
    //public 
    class Chat extends Sprite {
        private var _reactor:Reactor;
        private var _selfID:String;
        private var _userName:String;
        // 全体チャット用
        private var _roomIDForAll:String;
        private var _roomForAll:Room;
        // チームチャット用
        private var _roomForTeam:Room;
        private var _messageFiltersForTeam:IFilter;
        private var _colorForTeam:uint;
        private var _targetIsTeam:Boolean;
        // メッセージ管理
        private var _messages:Vector.<TextField>;
        private var _messagePool:Vector.<TextField>;
        private var _selectedMessageIndex:int;
        private var _clientFilterList:Vector.<String>;
        // 連投規制関連
        private var _lastPostedMessage:String;
        private var _lastPostedTargetIsTeam:Boolean;
        private var _lastPostedTime:int;
        private var _sendDelayTimer:Timer;
        private var _regulationCount:int;
        private var _isRestricted:Boolean;
        // 表示関連
        private var _statusBar:TextField;
        private var _messageArea:Sprite;
        private var _messageAreaMask:Sprite;
        private var _messageDisplay:Sprite;
        private var _scrollBar:VScrollBar;
        private var _targetLabelContainer:Sprite;
        private var _targetLabel:TextField;
        private var _inputForm:TextField;
        private var _addClientFilterButton:PushButton;
        private var _clearClientFilterButton:PushButton;
        private var _resizeGrip:Sprite;
        private var _resizeOffset:Point;
        
        private static const DEFAULT_USER_NAME:String = "名無し";
        private static const MESSAGE_NAME_FOR_ALL:String = "all";
        private static const MESSAGE_NAME_FOR_TEAM:String = "team";
        private static const MESSAGE_LOG_SIZE:int = 50;
        private static const MESSAGE_MAX_CHARS:int = 50;
        private static const SEND_RATE_LIMIT_HIGH:int = 1000;
        private static const SEND_RATE_LIMIT_LOW:int = 10000;
        private static const SEND_REGULATION:int = 3;
        private static const WINDOW_MIN_WIDTH:int = 232;
        private static const WINDOW_MIN_HEIGHT:int = 100;
        private static const STATUS_ON_CONNECTED:String = "現在の閲覧者数 %v 人";
        private static const STATUS_ON_DISCONNECTED:String = "サーバーに接続中です...";
        
        public function Chat(reactor:Reactor, roomIDForAll:String) {
            _reactor = reactor;
            _selfID = "";
            _userName = Chat.DEFAULT_USER_NAME;
            
            _roomIDForAll = roomIDForAll;
            _roomForAll = _roomForTeam = null;
            _messageFiltersForTeam = null;
            _colorForTeam = 0xFFFFFF;
            _targetIsTeam = false;
            
            _messages = new Vector.<TextField>();
            _messagePool = new Vector.<TextField>();
            for (var i:int = 0; i < Chat.MESSAGE_LOG_SIZE; i++) {
                _messagePool.push(createMessageBlock());
            }
            _selectedMessageIndex = -1;
            _clientFilterList = new Vector.<String>();
            
            _lastPostedMessage = "";
            _lastPostedTargetIsTeam = false;
            _lastPostedTime = 0;
            _sendDelayTimer = new Timer(Chat.SEND_RATE_LIMIT_HIGH, 1);
            _sendDelayTimer.addEventListener(TimerEvent.TIMER, sendMessage);
            _regulationCount = 0;
            _isRestricted = false;
            
            addChild(_messageArea = new Sprite());
            _messageArea.addChild(_messageAreaMask = new Sprite());
            _messageArea.mask = _messageAreaMask;
            _messageArea.addChild(_messageDisplay = new Sprite());
            addChild(_scrollBar = createScrollBar());
            addChild(_targetLabelContainer = new Sprite());
            _targetLabelContainer.addChild(_targetLabel = createTargetLabel());
            addChild(_inputForm = createInputForm());
            addChild(_addClientFilterButton = createFilterButton("+"));
            addChild(_clearClientFilterButton = createFilterButton("-"));
            addChild(_resizeGrip = createResizeGrip());
            addChild(_statusBar = createStatusBar());
            
            _resizeOffset = new Point();
            resize(Chat.WINDOW_MIN_WIDTH, Chat.WINDOW_MIN_HEIGHT);
            
            _statusBar.addEventListener(MouseEvent.MOUSE_DOWN, startDragHandler);
            _statusBar.addEventListener(MouseEvent.MOUSE_UP, stopDragHandler);
            _messageDisplay.addEventListener(MouseEvent.CLICK, onClickMessageBlock);
            _messageDisplay.addEventListener(MouseEvent.MOUSE_OVER, updateMessageCursor);
            _messageDisplay.addEventListener(MouseEvent.ROLL_OUT, updateMessageCursor);
            _scrollBar.addEventListener(Event.CHANGE, scrollMessageDisplay);
            _inputForm.addEventListener(FocusEvent.FOCUS_OUT, disableIME);
            _inputForm.addEventListener(KeyboardEvent.KEY_DOWN, postMessage);
            _addClientFilterButton.addEventListener(MouseEvent.CLICK, addClientToFilterList);
            _clearClientFilterButton.addEventListener(MouseEvent.CLICK, clearClientFilterList);
            _resizeGrip.addEventListener(MouseEvent.MOUSE_DOWN, startResizing);
            _resizeGrip.addEventListener(MouseEvent.MOUSE_UP, stopResizing);
            addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
            addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
        }
        
        private function createMessageBlock():TextField {
            var result:TextField = new TextField();
            result.filters = [new DropShadowFilter(1, 45, 0x444444, 1, 1, 1)];
            result.autoSize = TextFieldAutoSize.LEFT;
            result.wordWrap = true;
            result.defaultTextFormat = new TextFormat("_sans", 10, 0xFFFFFF);
            return result;
        }
        
        private function createStatusBar():TextField {
            var result:TextField = new TextField();
            result.height = 20;
            result.background = true; result.backgroundColor = 0x444444;
            result.filters = [new BevelFilter(1, 45, 0xCCCCCC, 1, 0x000000, 1, 0, 0)];
            result.selectable = false;
            result.defaultTextFormat = new TextFormat("_sans", 10, 0xFFFFFF, null, null, null, null, null, TextFormatAlign.CENTER);
            result.text = Chat.STATUS_ON_DISCONNECTED;
            return result;
        }
        
        private function createScrollBar():VScrollBar {
            var result:VScrollBar = new VScrollBar(null, 0, 20);
            result.lineSize = result.pageSize = 10;
            result.setSliderParams(0, 0, 0);
            return result;
        }
        
        private function createTargetLabel():TextField {
            var result:TextField = new TextField();
            result.width = 35; result.height = 18;
            result.filters = [new DropShadowFilter(1, 45, 0x444444, 1, 1, 1)];
            result.mouseEnabled = result.selectable = false;
            result.defaultTextFormat = new TextFormat("_sans", 10, 0xFFFFFF, null, null, null, null, null, TextFormatAlign.CENTER);
            result.text = "all";
            return result;
        }
        
        private function createInputForm():TextField {
            var result:TextField = new TextField();
            result.x = 35;
            result.height = 18;
            result.background = true; result.backgroundColor = 0xFFFFFF;
            result.filters = [new BevelFilter(1, 225, 0xCCCCCC, 1, 0x444444, 1, 1, 1)];
            result.maxChars = Chat.MESSAGE_MAX_CHARS;
            result.type = TextFieldType.INPUT;
            result.defaultTextFormat = new TextFormat("_sans", 10, 0x000000);
            return result;
        }
        
        private function createFilterButton(label:String):PushButton {
            var result:PushButton = new PushButton(null, 0, 0, label);
            result.width = result.height = 16; result.draw();
            result.enabled = false;
            return result;
        }
        
        private function createResizeGrip():Sprite {
            var result:Sprite = new Sprite();
            result.buttonMode = true;
            var size:int = 18;
            result.graphics.beginFill(0xFFFFFF, 0.5);
            result.graphics.moveTo(size, 0);
            result.graphics.lineTo(0, size);
            result.graphics.lineTo(size, size);
            result.graphics.lineTo(size, 0);
            result.graphics.endFill();
            return result;
        }
        
        private function startDragHandler(event:MouseEvent):void { startDrag(); }
        private function stopDragHandler(event:MouseEvent):void { stopDrag(); }
        
        private function onClickMessageBlock(event:MouseEvent):void {
            var messageBlock:TextField = event.target as TextField;
            if (!messageBlock || messageBlock.name == _selfID) { return; }
            
            var clickedMessageIndex:int = _messages.indexOf(messageBlock);
            setSelectedMessageIndex((clickedMessageIndex != _selectedMessageIndex) ? clickedMessageIndex : -1);
            updateMessageCursor();
        }
        
        private function scrollMessageDisplay(event:Event):void {
            _messageDisplay.y = -_scrollBar.value;
        }
        
        private function disableIME(event:FocusEvent):void {
            if (Capabilities.hasIME) { IME.enabled = false; }
        }
        
        private function addClientToFilterList(event:MouseEvent):void {
            var messageBlock:TextField = _messages[_selectedMessageIndex];
            var filteredID:String = messageBlock.name;
            _clientFilterList.push(filteredID);
            _clearClientFilterButton.enabled = true;
            
            for (var i:int = _messages.length - 1; i >= 0; i--) {
                messageBlock = _messages[i];
                if (messageBlock.name == filteredID) {
                    _messages.splice(i, 1);
                    _messagePool.push(messageBlock);
                    _messageDisplay.removeChild(messageBlock);
                }
            }
            
            setSelectedMessageIndex(-1);
            updateMessageDisplay();
            updateMessageCursor();
        }
        
        private function clearClientFilterList(event:MouseEvent):void {
            _clientFilterList.length = 0;
            _clearClientFilterButton.enabled = false;
        }
        
        private function startResizing(event:MouseEvent):void {
            _resizeOffset.setTo(_resizeGrip.x + 18 - mouseX, _resizeGrip.y + 18 - mouseY);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onResizing);
            addEventListener(MouseEvent.MOUSE_UP, stopResizing);
        }
        
        private function onResizing(event:MouseEvent):void {
            resize(mouseX + _resizeOffset.x, mouseY + _resizeOffset.y);
        }
        
        private function stopResizing(event:Event):void {
            removeEventListener(MouseEvent.MOUSE_UP, stopResizing);
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, onResizing);
        }
        
        private function addedToStageHandler(event:Event):void {
            _reactor.addEventListener(ReactorEvent.READY, joinRoom);
            _reactor.addEventListener(ReactorEvent.CLOSE, leaveRoom);
            if (_reactor.isReady()) { joinRoom(); }
        }
        
        private function removedFromStageHandler(event:Event):void {
            _reactor.removeEventListener(ReactorEvent.READY, joinRoom);
            _reactor.removeEventListener(ReactorEvent.CLOSE, leaveRoom);
            leaveRoom();
            disableTeamChat();
        }
        
        private function joinRoom(event:ReactorEvent = null):void {
            _selfID = _reactor.self().getClientID();
            
            var updateLevels:UpdateLevels = new UpdateLevels();
            updateLevels.clearAll();
            updateLevels.occupantCount = updateLevels.roomMessages = true;
            
            _roomForAll = _reactor.getRoomManager().createRoom(_roomIDForAll);
            _roomForAll.addEventListener(RoomEvent.OCCUPANT_COUNT, roomOccupantCountHandler);
            _roomForAll.addMessageListener(Chat.MESSAGE_NAME_FOR_ALL, receiveMessage);
            _roomForAll.join(null, updateLevels);
        }
        
        private function leaveRoom(event:ReactorEvent = null):void {
            if (_roomForAll) {
                _roomForAll.removeMessageListener(Chat.MESSAGE_NAME_FOR_ALL, receiveMessage);
                _roomForAll.removeEventListener(RoomEvent.OCCUPANT_COUNT, roomOccupantCountHandler);
                _roomForAll.leave();
            }
            
            _statusBar.text = Chat.STATUS_ON_DISCONNECTED;
        }
        
        private function roomOccupantCountHandler(event:RoomEvent):void {
            _statusBar.text = Chat.STATUS_ON_CONNECTED.replace(/%v/, event.getNumClients().toString());
        }
        
        private function postMessage(event:KeyboardEvent):void {
            if (!_reactor.isReady() || event.keyCode != Keyboard.ENTER || _inputForm.text == "") { return; }
            
            var postedTime:int = getTimer();
            _regulationCount = (postedTime - _lastPostedTime < Chat.SEND_RATE_LIMIT_LOW || _inputForm.text.length == Chat.MESSAGE_MAX_CHARS) ? _regulationCount + 1 : 0;
            _lastPostedTime = postedTime;
            if (_sendDelayTimer.running || _regulationCount >= Chat.SEND_REGULATION) { _isRestricted = true; }
            
            if (!_isRestricted) {
                _lastPostedMessage = _inputForm.text;
                _lastPostedTargetIsTeam = _targetIsTeam;
                _sendDelayTimer.start();
            }
            addMessage(_reactor.self().getClientID(), _userName, _inputForm.text, ((_targetIsTeam) ? _colorForTeam : 0xFFFFFF).toString());
            _inputForm.text = "";
        }
        
        private function sendMessage(event:TimerEvent):void {
            if (!_isRestricted) {
                var room:Room = _roomForAll;
                var messageName:String = Chat.MESSAGE_NAME_FOR_ALL;
                var filters:IFilter = null;
                var color:uint = 0xFFFFFF;
                
                if (_lastPostedTargetIsTeam) {
                    room = _roomForTeam;
                    messageName = Chat.MESSAGE_NAME_FOR_TEAM;
                    filters = _messageFiltersForTeam;
                    color = _colorForTeam;
                }
                
                room.sendMessage(messageName, false, filters, _userName, _lastPostedMessage, color.toString());
            }
        }
        
        private function receiveMessage(from:IClient, senderName:String, messageText:String, messageColor:String):void {
            var senderID:String = from.getClientID();
            if (_clientFilterList.indexOf(senderID) == -1) { addMessage(senderID, senderName, messageText, messageColor); }
        }
        
        private function addMessage(senderID:String, senderName:String, messageText:String, messageColor:String):void {
            var messageBlock:TextField;
            if (_messagePool.length) {
                messageBlock = _messagePool.pop();
            } else {
                messageBlock = _messages.shift();
                setSelectedMessageIndex(_selectedMessageIndex - 1);
            }
            messageBlock.name = senderID;
            messageBlock.text = "(" + senderID + ") " + senderName + ": " + messageText;
            messageBlock.textColor = uint(messageColor);
            _messages.push(messageBlock);
            _messageDisplay.addChild(messageBlock);
            
            updateMessageDisplay();
            updateMessageCursor();
        }
        
        private function setSelectedMessageIndex(value:int):void {
            _selectedMessageIndex = value;
            _addClientFilterButton.enabled = (_selectedMessageIndex >= 0);
        }
        
        private function updateMessageDisplay():void {
            var top:int = 0;
            for (var i:int = _messages.length - 1; i >= 0; i--) {
                var messageBlock:TextField = _messages[i];
                messageBlock.width = width - 10;
                top -= messageBlock.textHeight;
                messageBlock.y = top - 2;
            }
            top = Math.min(top, -_scrollBar.height);
            
            _scrollBar.minimum = top + _scrollBar.height;
            _scrollBar.setThumbPercent(_scrollBar.height / -top);
            _messageDisplay.y = -_scrollBar.value;
        }
        
        private function updateMessageCursor(event:MouseEvent = null):void {
            var messageBlock:TextField;
            if (_selectedMessageIndex >= 0) {
                messageBlock = _messages[_selectedMessageIndex];
            } else if (event) {
                messageBlock = event.target as TextField;
            }
            
            _messageDisplay.graphics.clear();
            if (messageBlock) {
                _messageDisplay.graphics.beginFill(0xFF0000, 0.5);
                _messageDisplay.graphics.drawRect(0, messageBlock.y + 2, messageBlock.width, messageBlock.textHeight);
                _messageDisplay.graphics.endFill();
            }
        }
        
        public function resize(width:int, height:int):void {
            width = Math.max(Chat.WINDOW_MIN_WIDTH, width);
            height = Math.max(Chat.WINDOW_MIN_HEIGHT, height);
            
            graphics.clear();
            graphics.beginFill(0x444444, 0.5);
            graphics.drawRect(0, 20, width, height - 20);
            graphics.endFill();
            _statusBar.width = width;
            _messageArea.y = height - 20;
            _messageAreaMask.graphics.clear();
            _messageAreaMask.graphics.beginFill(0x000000);
            _messageAreaMask.graphics.drawRect(0, -(height - 40), width - 10, height - 40);
            _messageAreaMask.graphics.endFill();
            _scrollBar.x = width - 10;
            _scrollBar.height = height - 40;
            _scrollBar.draw();
            _targetLabel.y = _inputForm.y = height - 19;
            _inputForm.width = width - 90;
            _addClientFilterButton.x = width - 53;
            _clearClientFilterButton.x = width - 36;
            _resizeGrip.x = width - 18;
            _addClientFilterButton.y = _clearClientFilterButton.y = _resizeGrip.y = height - 18;
            
            updateMessageDisplay();
            updateMessageCursor();
        }
        
        public function enableTeamChat(roomForTeam:Room, filters:IFilter = null, color:uint = 0xFFFFFF):void {
            _roomForTeam = roomForTeam;
            _roomForTeam.addMessageListener(Chat.MESSAGE_NAME_FOR_TEAM, receiveMessage);
            _messageFiltersForTeam = filters;
            _colorForTeam = color;
            
            _targetLabelContainer.buttonMode = true;
            _targetLabelContainer.addEventListener(MouseEvent.CLICK, toggleTarget);
        }
        
        private function toggleTarget(event:MouseEvent):void {
            _targetIsTeam = !_targetIsTeam;
            _targetLabel.text = (_targetIsTeam) ? "team" : "all";
        }
        
        public function disableTeamChat():void {
            _targetLabelContainer.removeEventListener(MouseEvent.CLICK, toggleTarget);
            _targetLabelContainer.buttonMode = false;
            
            if (_roomForTeam) { _roomForTeam.removeMessageListener(Chat.MESSAGE_NAME_FOR_TEAM, receiveMessage); }
            _targetIsTeam = false;
            _targetLabel.text = "all";
        }
        
        public function changeName(value:String):void { _userName = value || Chat.DEFAULT_USER_NAME; }
    }
//}
//package ore.orelib.commons {
    import com.bit101.components.PushButton;
    import com.bit101.components.Style;
    import flash.filters.BevelFilter;
    import flash.text.TextField;
    import flash.text.TextFieldType;
    import flash.text.TextFormat;
    import flash.text.TextFormatAlign;
    
    //public 
    class CustomComps {
        public static function createNameForm(width:int, fontSize:int = 12, maxChars:int = 12, restrict:String = "^|<>"):TextField {
            var result:TextField = new TextField();
            result.width = width;
            result.background = true; result.backgroundColor = 0xFFFFFF;
            result.filters = [new BevelFilter(1, 225, 0xCCCCCC, 1, 0x444444, 1, 1, 1)];
            result.maxChars = maxChars;
            result.restrict = restrict;
            result.type = TextFieldType.INPUT;
            result.defaultTextFormat = new TextFormat("_sans", fontSize, 0x000000, null, null, null, null, null, TextFormatAlign.CENTER);
            result.text = "a"; result.height = result.textHeight + 4; result.text = "";
            return result;
        }
        
        public static function createPushButton(x:Number, y:Number, label:String = "", handler:Function = null):PushButton {
            var temp:Object = { embedFonts: Style.embedFonts, fontName: Style.fontName, fontSize: Style.fontSize };
            Style.embedFonts = false; Style.fontName = "_sans"; Style.fontSize = 10;
            var result:PushButton = new PushButton(null, x, y, label, handler);
            Style.embedFonts = temp.embedFonts; Style.fontName = temp.fontName; Style.fontSize = temp.fontSize;
            return result;
        }
    }
//}
//package ore.orelib.commons {
    import flash.errors.IllegalOperationError;
    import flash.events.EventDispatcher;
    
    //public 
    class EventManager extends EventDispatcher {
        private static var _instance:EventManager;
        private static var _allowsInstantiation:Boolean = false;
        
        public static function get instance():EventManager {
            if (!_instance) {
                _allowsInstantiation = true;
                _instance = new EventManager();
                _allowsInstantiation = false;
            }
            
            return _instance;
        }
        
        public function EventManager() {
            if (!_allowsInstantiation) { throw new IllegalOperationError("EventManager class is a Singleton!"); }
        }
    }
//}
//package ore.orelib.commons {
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.events.ContextMenuEvent;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.ui.ContextMenu;
    
    //public 
    class Key {
        private static var _stage:Stage;
        private static var _currentStates:Vector.<Boolean>;
        private static var _previousStates:Vector.<Boolean>;
        
        public static const MOUSE_LEFT:uint = 0;
        
        public static function init(documentClass:Sprite):void {
            _stage = documentClass.stage;
            _currentStates = new Vector.<Boolean>(256, true);
            _previousStates = new Vector.<Boolean>(256, true);
            
            _stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
            _stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
            _stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
            _stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
            _stage.addEventListener(Event.EXIT_FRAME, update);
            _stage.addEventListener(Event.DEACTIVATE, clear);
            
            var contextMenu:ContextMenu = new ContextMenu();
            contextMenu.hideBuiltInItems();
            contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, clear);
            documentClass.contextMenu = contextMenu;
        }
        
        private static function keyDownHandler(event:KeyboardEvent):void { _currentStates[event.keyCode] = true; }
        private static function keyUpHandler(event:KeyboardEvent):void { _currentStates[event.keyCode] = false; }
        private static function mouseDownHandler(event:MouseEvent):void { _currentStates[Key.MOUSE_LEFT] = true; }
        private static function mouseUpHandler(event:MouseEvent):void { _currentStates[Key.MOUSE_LEFT] = false; }
        
        private static function update(event:Event):void {
            for (var i:int = 0; i < 256; i++) {
                _previousStates[i] = _currentStates[i];
            }
        }
        
        private static function clear(event:Event):void {
            for (var i:int = 0; i < 256; i++) {
                _currentStates[i] = false;
            }
        }
        
        public static function isDown(keyCode:uint):Boolean { return _stage.focus == null && _currentStates[keyCode]; }
        public static function pressed(keyCode:uint):Boolean { return Key.isDown(keyCode) && !_previousStates[keyCode]; }
    }
//}
//package ore.orelib.commons {
    import flash.geom.Point;
    import flash.text.AntiAliasType;
    import flash.text.GridFitType;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    import flash.text.TextFormatAlign;
    
    //public 
    class Labeler {
        private var _hAlign:String;
        private var _autoSize:String;
        private var _vAlign:String;
        private var _background:Boolean;
        private var _backgroundColor:uint;
        private var _filters:Array;
        private var _fontName:String;
        private var _sharpness:Number;
        private var _thickness:Number;
        private var _fontColor:uint;
        private var _fontSize:int;
        private var _position:Point;
        private var _selectable:Boolean;
        private var _size:Point;
        private var _wordWrap:Boolean;
        
        public static const NONE:String = "none";
        public static const LEFT:String = "left";
        public static const CENTER:String = "center";
        public static const RIGHT:String = "right";
        public static const TOP:String = "top";
        public static const MIDDLE:String = "middle";
        public static const BOTTOM:String = "bottom";
        private static const DEVICE_FONT:String = "_sans";
        
        public function Labeler() {
            _hAlign = TextFormatAlign.LEFT;
            _autoSize = TextFieldAutoSize.NONE;
            _vAlign = Labeler.TOP;
            _background = false;
            _backgroundColor = 0xFFFFFF;
            _filters = [];
            _fontName = Labeler.DEVICE_FONT;
            _sharpness = _thickness = 0;
            _fontColor = 0x000000;
            _fontSize = 12;
            _position = new Point(0, 0);
            _size = new Point(100, 100);
            _selectable = _wordWrap = false;
        }
        
        public function align(value:String = Labeler.LEFT):Labeler {
            switch(value) {
                case Labeler.CENTER: { _hAlign = TextFormatAlign.CENTER; break; }
                case Labeler.RIGHT: { _hAlign = TextFormatAlign.RIGHT; break; }
                case Labeler.LEFT: default: { _hAlign = TextFormatAlign.LEFT; break; }
            }
            return this;
        }
        
        public function autoSize(horizontal:String = Labeler.NONE, vertical:String = Labeler.TOP):Labeler {
            switch(horizontal) {
                case Labeler.LEFT: { _autoSize = TextFieldAutoSize.LEFT; break; }
                case Labeler.CENTER: { _autoSize = TextFieldAutoSize.CENTER; break; }
                case Labeler.RIGHT: { _autoSize = TextFieldAutoSize.RIGHT; break; }
                case Labeler.NONE: default: { _autoSize = TextFieldAutoSize.NONE; break; }
            }
            _vAlign = vertical;
            return this;
        }
        
        public function background(enabled:Boolean = true, color:uint = 0xFF0000):Labeler { _background = enabled; _backgroundColor = color; return this; }
        public function filters(value:Array):Labeler { _filters = value; return this; }
        public function font(name:String, sharpness:Number = 0, thickness:Number = 0):Labeler { _fontName = name; _sharpness = sharpness; _thickness = thickness; return this; }
        public function fontColor(value:uint):Labeler { _fontColor = value; return this; }
        public function fontSize(value:int):Labeler { _fontSize = value; return this; }
        public function offset(x:Number, y:Number):Labeler { _position.offset(x, y); return this; }
        public function pos(x:Number, y:Number):Labeler { _position.setTo(x, y); return this; }
        public function selectable(enabled:Boolean = true):Labeler { _selectable = enabled; return this; }
        public function size(width:Number, height:Number):Labeler { _size.setTo(width, height); return this; }
        public function wordWrap(enabled:Boolean = true):Labeler { _wordWrap = enabled; return this; }
        
        public function build(text:String):TextField {
            var result:TextField = new TextField();
            result.x = _position.x; result.width = _size.x; result.height = _size.y;
            result.autoSize = _autoSize;
            result.background = _background; result.backgroundColor = _backgroundColor;
            result.filters = _filters;
            result.mouseEnabled = result.selectable = _selectable;
            result.wordWrap = _wordWrap;
            result.defaultTextFormat = new TextFormat(_fontName, _fontSize, _fontColor, null, null, null, null, null, _hAlign);
            if (_fontName != Labeler.DEVICE_FONT) {
                result.embedFonts = true;
                result.antiAliasType = AntiAliasType.ADVANCED;
                result.gridFitType = (_hAlign == TextFormatAlign.LEFT) ? GridFitType.PIXEL : GridFitType.SUBPIXEL;
                result.sharpness = _sharpness; result.thickness = _thickness;
            }
            result.text = text;
            switch(_vAlign) {
                case Labeler.MIDDLE: { result.y = _position.y + (_size.y - result.height) / 2; break; }
                case Labeler.BOTTOM: { result.y = _position.y + (_size.y - result.height); break; }
                case Labeler.TOP: default: { result.y = _position.y; break; }
            }
            return result;
        }
    }
//}
//package ore.orelib.commons {
    import com.bit101.components.ProgressBar;
    import com.bit101.components.PushButton;
    import flash.display.DisplayObjectContainer;
    import flash.display.Loader;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    import flash.utils.Dictionary;
    import net.user1.reactor.Reactor;
    import net.user1.reactor.ReactorEvent;
    import net.wonderfl.utils.FontLoader;
    
    [Event(name = "complete", type = "flash.events.Event")]
    //public 
    class Preloader extends EventDispatcher {
        private var _progressBar:ProgressBar;
        private var _reactor:Reactor;
        private var _alterHost:String;
        private var _alterPort:int;
        private var _loaders:Dictionary;
        private var _fonts:Vector.<String>;
        
        public function Preloader(parent:DisplayObjectContainer) {
            _progressBar = new ProgressBar(parent, 182, 227);
            _progressBar.maximum = 0;
            
            _reactor = null;
            _loaders = new Dictionary();
            _fonts = new Vector.<String>();
        }
        
        public function addReactorConnectionRequest(reactor:Reactor, alterHost:String = "tryunion.com", alterPort:int = 80):void {
            _reactor = reactor;
            _alterHost = alterHost;
            _alterPort = alterPort;
        }
        
        public function addLoaderRequest(...urls):void {
            for each(var url:String in urls) {
                _loaders[url] = new Loader();
            }
        }
        
        public function addFontLoaderRequest(...fontNames):void {
            for each(var fontName:String in fontNames) {
                _fonts.push(fontName);
            }
        }
        
        public function load(appID:String = "", parentAppID:String = "sKs2"):void {
            if (_reactor) {
                _progressBar.maximum++;
                _reactor.addEventListener(ReactorEvent.READY, onLoaded);
                _reactor.connect((appID == parentAppID) ? "49.212.153.80" : _alterHost, _alterPort);
            }
            
            for (var url:String in _loaders) {
                _progressBar.maximum++;
                var loader:Loader = _loaders[url];
                loader.contentLoaderInfo.addEventListener(Event.INIT, onLoaded);
                loader.load(new URLRequest(url), new LoaderContext(true));
            }
            
            for each(var fontName:String in _fonts) {
                _progressBar.maximum++;
                var fontLoader:FontLoader = new FontLoader();
                fontLoader.addEventListener(Event.COMPLETE, onLoaded);
                fontLoader.load(fontName);
            }
            
            if (_progressBar.maximum == 0) { onLoaded(); }
            
            function onLoaded(event:Event = null):void {
                if (event) { event.currentTarget.removeEventListener(event.type, arguments.callee); }
                if (++_progressBar.value >= _progressBar.maximum) {
                    _progressBar.parent.removeChild(_progressBar);
                    dispatchEvent(new Event(Event.COMPLETE));
                }
            }
        }
        
        public function get loaders():Dictionary { return _loaders; }
    }
//}
//package ore.orelib.commons {
    //public 
    class sint {
        private var _key:int;
        private var _cipher:int;
        
        public function sint(val:int = 0) {
            this.value = val;
        }
        
        public function get value():int { return _cipher ^ _key; }
        public function set value(val:int):void {
            _key = 0xFFFFFFFF * Math.random();
            _cipher = val ^ _key;
        }
    }
//}
//package ore.orelib.commons {
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    
    /* flash.geom パッケージ内クラスのテンポラリオブジェクトを再利用するためのクラスです。 */
    //public 
    class Temp {
        private static var _capacity:int;
        
        private static var _colorTransforms:Vector.<ColorTransform>;
        private static var _matrices:Vector.<Matrix>;
        private static var _points:Vector.<Point>;
        private static var _rectangles:Vector.<Rectangle>;
        
        private static var _colorTransformsIndex:int;
        private static var _matricesIndex:int;
        private static var _pointsIndex:int;
        private static var _rectanglesIndex:int;
        
        public static function init(capacity:int = 3):void {
            _capacity = Math.max(1, capacity);
            
            _colorTransforms = new Vector.<ColorTransform>(_capacity, true);
            _matrices = new Vector.<Matrix>(_capacity, true);
            _points = new Vector.<Point>(_capacity, true);
            _rectangles = new Vector.<Rectangle>(_capacity, true);
            
            for (var i:int = 0; i < _capacity; i++) {
                _colorTransforms[i] = new ColorTransform();
                _matrices[i] = new Matrix();
                _points[i] = new Point();
                _rectangles[i] = new Rectangle();
            }
            
            _colorTransformsIndex = _matricesIndex = _pointsIndex = _rectanglesIndex = 0;
        }
        
        public static function colorTransform(redMultiplier:Number = 1, greenMultiplier:Number = 1, blueMultiplier:Number = 1, alphaMultiplier:Number = 1, redOffset:Number = 0, greenOffset:Number = 0, blueOffset:Number = 0, alphaOffset:Number = 0):ColorTransform {
            var result:ColorTransform = _colorTransforms[_colorTransformsIndex++];
            if (_colorTransformsIndex >= _capacity) { _colorTransformsIndex = 0; }
            
            result.redMultiplier = redMultiplier; result.greenMultiplier = greenMultiplier; result.blueMultiplier = blueMultiplier; result.alphaMultiplier = alphaMultiplier;
            result.redOffset = redOffset; result.greenOffset = greenOffset; result.blueOffset = blueOffset; result.alphaOffset = alphaOffset;
            
            return result;
        }
        
        public static function matrix(a:Number = 1, b:Number = 0, c:Number = 0, d:Number = 1, tx:Number = 0, ty:Number = 0):Matrix {
            var result:Matrix = _matrices[_matricesIndex++];
            if (_matricesIndex >= _capacity) { _matricesIndex = 0; }
            
            result.setTo(a, b, c, d, tx, ty);
            
            return result;
        }
        
        public static function point(x:Number = 0, y:Number = 0):Point {
            var result:Point = _points[_pointsIndex++];
            if (_pointsIndex >= _capacity) { _pointsIndex = 0; }
            
            result.setTo(x, y);
            
            return result;
        }
        
        public static function rectangle(x:Number = 0, y:Number = 0, width:Number = 0, height:Number = 0):Rectangle {
            var result:Rectangle = _rectangles[_rectanglesIndex++];
            if (_rectanglesIndex >= _rectangles.length) { _rectanglesIndex = 0; }
            
            result.setTo(x, y, width, height);
            
            return result;
        }
    }
//}
//package ore.orelib.commons {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.filters.DropShadowFilter;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.utils.Timer;
    import net.user1.reactor.Reactor;
    import net.user1.reactor.Statistics;
    
    //public 
    class UnionStats extends Sprite {
        private var _reactor:Reactor;
        private var _fpsCount:int;
        private var _updateTimer:Timer;
        
        private var _fpsLabel:TextField;
        private var _stageFpsLabel:TextField;
        private var _pingLabel:TextField;
        private var _memLabel:TextField;
        private var _downLabel:TextField;
        private var _upLabel:TextField;
        private var _peakMemLabel:TextField;
        private var _peakDownLabel:TextField;
        private var _peakUpLabel:TextField;
        
        public function UnionStats(reactor:Reactor) {
            _reactor = reactor;
            _fpsCount = 0;
            _updateTimer = new Timer(1000);
            _updateTimer.addEventListener(TimerEvent.TIMER, update);
            
            graphics.beginFill(0x444444, 0.8);
            graphics.drawRect(0, 0, 110, 92);
            graphics.endFill();
            graphics.beginFill(0xFFFFFF);
            graphics.drawRect(5, 37, 100, 2);
            graphics.endFill();
            
            addChild(createTextField("FPS:", 2, 2, 35, "left"));
            addChild(createTextField("Mem:", 2, 18, 35, "left"));
            addChild(createTextField("Ping:", 2, 42, 35, "left"));
            addChild(createTextField("Down:", 2, 58, 35, "left"));
            addChild(createTextField("Up:", 2, 74, 35, "left"));
            addChild(createTextField("/", 69, 2, 7, "center"));
            addChild(createTextField("/", 69, 18, 7, "center"));
            addChild(createTextField("/", 69, 58, 7, "center"));
            addChild(createTextField("/", 69, 74, 7, "center"));
            
            addChild(_fpsLabel = createTextField("0", 37, 2, 32, "right"));
            addChild(_stageFpsLabel = createTextField("0", 76, 2, 32, "left"));
            addChild(_pingLabel = createTextField("-1", 37, 42, 71, "center"));
            addChild(_memLabel = createTextField("0.00", 37, 18, 32, "right"));
            addChild(_downLabel = createTextField("0.00", 37, 58, 32, "right"));
            addChild(_upLabel = createTextField("0.00", 37, 74, 32, "right"));
            addChild(_peakMemLabel = createTextField("0.00", 76, 18, 32, "left"));
            addChild(_peakDownLabel = createTextField("0.00", 76, 58, 32, "left"));
            addChild(_peakUpLabel = createTextField("0.00", 76, 74, 32, "left"));
            
            addEventListener(MouseEvent.MOUSE_DOWN, startDragHandler);
            addEventListener(MouseEvent.MOUSE_UP, stopDragHandler);
            enable();
        }
        
        private function createTextField(text:String, x:int, y:int, width:int, align:String):TextField {
            var result:TextField = new TextField();
            result.x = x; result.y = y;
            result.width = width; result.height = 16;
            result.filters = [new DropShadowFilter(1, 45, 0x444444, 1, 1, 1)];
            result.mouseEnabled = result.selectable = false;
            var format:TextFormat = new TextFormat("_sans", 9, 0xFFFFFF, true);
            format.align = align;
            result.defaultTextFormat = format;
            result.text = text;
            return result;
        }
        
        private function startDragHandler(event:MouseEvent):void { startDrag(); }
        private function stopDragHandler(event:MouseEvent):void { stopDrag(); }
        private function enterFrameHandler(event:Event):void { _fpsCount++; }
        
        private function update(event:TimerEvent):void {
            _fpsLabel.text = _fpsCount.toString();
            _fpsCount = 0;
            if (stage) { _stageFpsLabel.text = stage.frameRate.toString(); }
            
            if (!_reactor.isReady()) { return; }
            var stats:Statistics = _reactor.getStatistics();
            _pingLabel.text = _reactor.self().getPing().toString();
            _memLabel.text = stats.getTotalMemoryMB().toFixed(2);
            _downLabel.text = stats.getKBReceivedPerSecond().toFixed(2);
            _upLabel.text = stats.getKBSentPerSecond().toFixed(2);
            _peakMemLabel.text = stats.getPeakMemoryMB().toFixed(2);
            _peakDownLabel.text = stats.getPeakKBReceivedPerSecond().toFixed(2);
            _peakUpLabel.text = stats.getPeakKBSentPerSecond().toFixed(2);
        }
        
        public function enable():void {
            _reactor.enableStatistics();
            _reactor.getStatistics().start();
            
            _fpsCount = 0;
            _updateTimer.start();
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
        }
        
        public function disable():void {
            _reactor.getStatistics().stop();
            _reactor.disableStatistics();
            
            _updateTimer.stop();
            removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
        }
    }
//}
//package ore.orelib.commons {
    /** Unionの属性値・メッセージ用の圧縮変換アルゴリズム */
    //public 
    class UPCConv {
        public static const VALID:String = "0123456789"
            + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            + "abcdefghijklmnopqrstuvwxyz"
            + "!\"#$%&\'()+/:;=?@[\\]^_`{}~";
        public static const INVALID:String = "*|<> ,.-";
        public static const VALID_LENGTH:int = 87;
        
        /** 整数値を符号に変換する */
        public static function encode(value:int):String {
            if (value == 0) { return "0"; }
            
            var result:String = (value < 0) ? (value = -(value), "-") : "";
            while (value) {
                result += UPCConv.VALID.charAt(value % UPCConv.VALID_LENGTH);
                value /= UPCConv.VALID_LENGTH;
            }
            return result;
        }
        
        /** 符号を整数値に変換する */
        public static function decode(code:String):int {
            var result:uint = 0;
            while (code) {
                var lastChar:String = code.substr(-1);
                if (lastChar == "-") {
                    result = -(result);
                } else {
                    result *= UPCConv.VALID_LENGTH;
                    result += UPCConv.VALID.indexOf(lastChar);
                }
                code = code.substring(0, code.length - 1);
            }
            return result;
        }
    }
//}
//package ore.orelib.data {
    //public 
    class Const {
        public static const FRAME_RATE:int = 45;
        public static const STAGE_SIZE:int = 2000; //(px)
        public static const TEAMBASE_SIZE:int = 400; //(px)
        public static const CONTROLPOINT_RADIUS:int = 100; //(px)
        public static const CONTROLPOINT_CAPTURE_TIME:int = 5000; //(ms)
        
        public static const PLAYER_HP:int = 10;
        public static const PLAYER_EN:int = 6000;
        public static const PLAYER_EN_COST:int = 800;
        public static const PLAYER_RESPAWN_TIME:int = 10000; //(ms)
        public static const PLAYER_FIRERATE:int = 200; //(ms)
        public static const PLAYER_SPEED:int = 180 / FRAME_RATE; //(px/fr)
        public static const PLAYER_ACCEL:Number = 360 / (FRAME_RATE * FRAME_RATE); //(px/fr2)
        public static const PLAYER_SEND_INTERVAL:int = 100; //(ms)
        public static const PLAYER_SQ_SPEED:int = PLAYER_SPEED * PLAYER_SPEED;
        public static const PLAYER_SPEED_PER_SECOND:int = PLAYER_SPEED * FRAME_RATE; //(px/s)
        
        public static const TURRET_CONVERGENCE_PERIOD:int = 250; //(ms)
        public static const TURRET_RADIUS:int = 16; //(px)
        
        public static const BULLET_SPEED:Number = 360 / 1000; //(px/ms)
        public static const BULLET_LIFETIME:int = 1500; //(ms)
        public static const BULLET_RADIUS:int = 4; //(px)
        
        public static const SCORE_KILL:int = 10;
        public static const SCORE_CAPTURE:int = 3;
        public static const RESTORE_KILL:int = 0;
        public static const RESTORE_CAPTURE:int = 1;
        
        public static const SETUP_DURATION:int = 31000; //(ms)
        public static const PLAYING_DURATION:int = 301000; //(ms)
        public static const GAME_DURATION:int = Const.SETUP_DURATION + Const.PLAYING_DURATION;
        
        public static const COLOR_RED:uint = 0xFF88CC;
        public static const COLOR_BLUE:uint = 0x88CCFF;
        
        public static const IMAGE_LOADER_CONTROLS:String = "loaderControls";
        public static const IMAGE_RED_TURRET:String = "redTurret";
        public static const IMAGE_BLUE_TURRET:String = "blueTurret";
        public static const IMAGE_RED_BULLET:String = "redBullet";
        public static const IMAGE_BLUE_BULLET:String = "buleBullet";
        public static const IMAGE_INDICATOR:String = "indicator";
        public static const IMAGE_BACKGROUND:String = "background";
        public static const IMAGE_HIT_EFFECT_ANIM:String = "hitEffectAnim";
        public static const IMAGE_KILLED_EFFECT_ANIM:String = "killedEffectAnim";
        
        public static const TEAM_RED:String = "r";
        public static const TEAM_BLUE:String = "b";
        public static const ATTR_NAME:String = "n";
        public static const ATTR_SCORE:String = "s";
        public static const ATTR_TEAM:String = "t";
        public static const ATTR_STATES:String = "o";
        public static const ATTR_PING:String = "p";
        public static const MESSAGE_SHOOT:String = "s";
        public static const MESSAGE_HIT:String = "d";
        public static const MESSAGE_KILLED:String = "k";
        
        public static const FONT:String = "IPAGP";
        public static const IMAGE_URL:String = "http://assets.wonderfl.net/images/related_images/1/1d/1da5/1da5c936e7265b2388c37538e0469be4ccde238e";
        public static const HINTS:Array = [
            "大人数で遊びたい人は午後10時に集合するか、誰かを誘ってやろう!"
        ];
        /*
        public static const HISTORY:String = ""
            + "2012/07/03 pingがより安定するように改善しました\n"
            + "2012/06/23 撃墜:占領の点数を2:1から10:3に変更しました\n"
            + "2012/05/09 送信頻度を再調整し相手の座標の精度を向上させました\n"
            + "2012/05/03 フォーカスが外れた際の自動退出に猶予時間を設けました\n"
            + "2012/03/08 描画の最適化を行い少し軽くしました\n"
            + "2012/03/06 フレームレートと送信頻度を下げ少し軽くしました\n"
            + "2012/03/05 自分にスコアが入るログを強調するようにしました\n"
            + "2012/03/05 キャプチャ時・自滅時のログを追加しました\n"
            + "2012/03/05 各プレイヤーのpingが表示されるようにしました\n"
            + "2012/03/03 自滅時に減点されるようにしました\n"
            + "2012/03/03 公開";
        */
    }
//}