Advertisement
Guest User

Untitled

a guest
Aug 21st, 2019
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import * as PIXI from 'pixi.js-legacy';
  2. import { OnClick } from '../../../common/interactions/OnClick';
  3. import { OnDispose } from '../../../common/interactions/OnDispose';
  4. import { OnStart } from '../../../common/interactions/OnStart';
  5. import { Direction } from '../../../common/position/Direction';
  6. import { SpriteContainer } from '../../../common/SpriteContainer';
  7. import { Nitro } from '../../../Nitro';
  8. import { UnitLookComposer } from '../../../packets/outgoing/room/unit/UnitLookComposer';
  9. import { RoomConfiguration } from '../../room/map/RoomConfiguration';
  10. import { UnitStatusType } from '../../room/unit/status';
  11. import { Unit } from '../../room/unit/Unit';
  12. import { UnitHandItem } from '../../room/unit/UnitHandItem';
  13. import { AvatarAction } from '../base/AvatarAction';
  14. import { AvatarBodyPart } from '../base/AvatarBodyPart';
  15. import { BaseAvatar } from '../base/BaseAvatar';
  16. import { BaseAvatarPart } from '../base/BaseAvatarPart';
  17. import { IPartData } from '../interfaces/IPartData';
  18.  
  19. export class AvatarBuilder extends SpriteContainer implements OnStart, OnDispose, OnClick
  20. {
  21.     public static HEAD_PARTS    = [ AvatarBodyPart.HEAD, AvatarBodyPart.HEAD_ACCESSORY, AvatarBodyPart.HEAD_ACCESSORY_EXTRA, AvatarBodyPart.HAIR, AvatarBodyPart.HAIR_BIG, AvatarBodyPart.EYES, AvatarBodyPart.EYE_ACCESSORY, AvatarBodyPart.FACE, AvatarBodyPart.FACE_ACCESSORY ];
  22.  
  23.     public static GESTURE_PARTS = [ AvatarBodyPart.FACE, AvatarBodyPart.EYES ];
  24.  
  25.     public static LEFT_PARTS    = [ AvatarBodyPart.LEFT_HAND, AvatarBodyPart.LEFT_HAND_ITEM, AvatarBodyPart.LEFT_SLEEVE, AvatarBodyPart.LEFT_COAT_SLEEVE ];
  26.     public static RIGHT_PARTS   = [ AvatarBodyPart.RIGHT_HAND, AvatarBodyPart.RIGHT_HAND_ITEM, AvatarBodyPart.RIGHT_SLEEVE, AvatarBodyPart.RIGHT_COAT_SLEEVE ];
  27.  
  28.     public static IGNORES_WALK  = [ ...AvatarBuilder.HEAD_PARTS, AvatarBodyPart.CHEST, AvatarBodyPart.CHEST_ACCESSORY, AvatarBodyPart.CHEST_PRINT, AvatarBodyPart.COAT_CHEST, AvatarBodyPart.WAIST_ACCESSORY ];
  29.  
  30.     public static IGNORES_SIT   = AvatarBuilder.IGNORES_WALK;
  31.  
  32.     public static EXPRESSIONS_LEFT: AvatarAction[]   = [ AvatarAction.EXPRESSION_WAVE ];
  33.     public static EXPRESSIONS_RIGHT: AvatarAction[]  = [ AvatarAction.CARRY, AvatarAction.EXPRESSION_LAUGH, AvatarAction.EXPRESSION_BLOW ];
  34.  
  35.     public static ACTIVATES_ANIMATION: AvatarAction[] = [ AvatarAction.POSTURE_WALK, AvatarAction.EXPRESSION_WAVE ];
  36.  
  37.     private _unit: Unit;
  38.  
  39.     private _direction: Direction;
  40.     private _headDirection: Direction;
  41.  
  42.     private _posture: AvatarAction;
  43.     private _gesture: AvatarAction;
  44.     private _expression: AvatarAction;
  45.     private _carryItem: UnitHandItem;
  46.     private _isUsing: boolean;
  47.     private _shadow: PIXI.Sprite;
  48.  
  49.     private _gestureTimeout: any;
  50.     private _expressionTimeout: any;
  51.     private _blinkInterval: any;
  52.     private _useInterval: any;
  53.  
  54.     private _isReady: boolean;
  55.     private _didCreateShadow: boolean;
  56.  
  57.     constructor(unit: Unit)
  58.     {
  59.         super();
  60.  
  61.         if(!(unit instanceof Unit)) throw new Error('invalid_unit');
  62.  
  63.         this._unit = unit;
  64.  
  65.         this._direction         = Direction.NORTH;
  66.         this._headDirection     = Direction.NORTH;
  67.  
  68.         this._posture           = AvatarAction.POSTURE_STAND;
  69.         this._gesture           = null;
  70.         this._expression        = null;
  71.         this._carryItem         = null;
  72.         this._isUsing           = false;
  73.         this._shadow            = null;
  74.  
  75.         this._gestureTimeout    = null;
  76.         this._expressionTimeout = null;
  77.         this._blinkInterval     = null;
  78.         this._useInterval       = null;
  79.  
  80.         this._isReady           = false;
  81.         this._didCreateShadow   = false;
  82.     }
  83.  
  84.     public onStart(): void
  85.     {
  86.         this._unit.room.mapManager.collisionMap.layerMap.addChild(this);
  87.  
  88.         this.toggleReadyness(null);
  89.  
  90.         this.updateView();
  91.     }
  92.  
  93.     public toggleReadyness(flag: boolean): void
  94.     {
  95.         if(flag === null) return this.toggleReadyness(this._unit.figure.isDownloaded);
  96.  
  97.         if(!flag) this.alpha = 0.80;
  98.         else this.alpha = 1;
  99.  
  100.         this._isReady = flag;
  101.     }
  102.  
  103.     public onUpdate(): void
  104.     {
  105.         this.setActions();
  106.        
  107.         if(!this.needsUpdate && !this.tween) return;
  108.  
  109.         super.onUpdate();
  110.  
  111.         const frameCount = Math.round(this.totalTimeRunning / SpriteContainer.FPS_TIME_MS);
  112.  
  113.         if(this.frameCount === frameCount) return;
  114.        
  115.         this.frameCount = frameCount;
  116.  
  117.         this.updateView();
  118.  
  119.         this.needsUpdate = false;
  120.     }
  121.  
  122.     public onClick(event: MouseEvent): void
  123.     {
  124.         Nitro.networkManager.processOutgoing(new UnitLookComposer(this._unit.position));
  125.     }
  126.  
  127.     public onDispose(): void
  128.     {
  129.         if(this._gestureTimeout) clearTimeout(this._gestureTimeout);
  130.         if(this._expressionTimeout) clearTimeout(this._expressionTimeout);
  131.         if(this._blinkInterval) clearInterval(this._blinkInterval);
  132.         if(this._useInterval) clearInterval(this._useInterval);
  133.  
  134.         this.stopTweening();
  135.     }
  136.  
  137.     private setActions(): void
  138.     {
  139.         if(!this._unit) return;
  140.  
  141.         let didSetPosture = false;
  142.  
  143.         if(this._unit.hasStatus(UnitStatusType.MOVE))
  144.         {
  145.             this.setPosture(AvatarAction.POSTURE_WALK);
  146.  
  147.             didSetPosture = true;
  148.         }
  149.  
  150.         if(this._unit.hasStatus(UnitStatusType.SIT))
  151.         {
  152.             this.setPosture(AvatarAction.POSTURE_SIT);
  153.  
  154.             didSetPosture = true;
  155.         }
  156.  
  157.         if(this._unit.hasStatus(UnitStatusType.LAY))
  158.         {
  159.             this.setPosture(AvatarAction.POSTURE_LAY);
  160.  
  161.             didSetPosture = true;
  162.         }
  163.        
  164.         if(!didSetPosture) this.setPosture(AvatarAction.POSTURE_STAND);
  165.  
  166.         if(AvatarBuilder.ACTIVATES_ANIMATION.indexOf(this._expression) !== -1) this.needsUpdate = true;
  167.     }
  168.  
  169.     public updateView(): void
  170.     {
  171.         this.destroyChildren();
  172.  
  173.         this.destroyTempSprites();
  174.  
  175.         if(!this._didCreateShadow) this.createShadow();
  176.  
  177.         if(this._shadow && !this._unit.hasStatus(UnitStatusType.SIT, UnitStatusType.LAY)) this.addChild(this._shadow);
  178.  
  179.         const x = this._unit.position.screenX;
  180.         const y = this._unit.position.screenY - RoomConfiguration.TILE_HEIGHT - this._unit.position.screenZ;
  181.  
  182.         const parts = this._unit.figure.parts;
  183.  
  184.         if(!parts) return;
  185.  
  186.         const totalParts = parts.length;
  187.  
  188.         if(!totalParts) return;
  189.  
  190.         for(let i = 0; i < totalParts; i++)
  191.         {
  192.             const part = parts[i];
  193.  
  194.             if(!part) continue;
  195.  
  196.             if(this._unit.figure.partsHidden.indexOf(part.type) !== -1) continue;
  197.  
  198.             const generated = this.generateBodyPart(part);
  199.  
  200.             if(!generated) continue;
  201.  
  202.             if(part.setData.setType.type === AvatarBodyPart.HEAD) this.addTempSelectableForLayer(generated, x, y);
  203.  
  204.             this.addChild(generated);
  205.         }
  206.  
  207.         if(this._carryItem)
  208.         {
  209.             const itemid = this._carryItem === 19 ? 5 : this._carryItem;
  210.  
  211.             const handItem = BaseAvatar.createHandItem(this._isUsing ? AvatarAction.DRINK : AvatarAction.CARRY, AvatarBodyPart.RIGHT_HAND_ITEM, this._direction, itemid);
  212.  
  213.             if(handItem) this.addChild(handItem);
  214.         }
  215.     }
  216.  
  217.     private destroyChildren(): void
  218.     {
  219.         const totalChildren = this.children.length;
  220.  
  221.         if(!totalChildren) return;
  222.  
  223.         for(let i = 0; i < totalChildren; i++)
  224.         {
  225.             const child = this.children[i];
  226.  
  227.             if(!child) continue;
  228.  
  229.             if(child === this._shadow) continue;
  230.  
  231.             child.destroy();
  232.         }
  233.  
  234.         this.removeChildren();
  235.     }
  236.  
  237.     private addTempSelectableForLayer(layer: PIXI.Sprite, x: number, y: number): void
  238.     {
  239.         if(!layer) return;
  240.  
  241.         const isScaling = layer.scale.x === -1;
  242.  
  243.         const selectable = this.getSelectable(layer.name, isScaling);
  244.  
  245.         if(!selectable) return;
  246.  
  247.         const body = BaseAvatar.getBaseFromPart('hh_human_body');
  248.  
  249.         if(!body) return;
  250.  
  251.         const asset = body.partData.assets[layer.name];
  252.  
  253.         if(!asset) return;
  254.  
  255.         const position = layer.position.clone();
  256.  
  257.         if(isScaling)
  258.         {
  259.             position.x = -layer.width + asset.x;
  260.  
  261.             position.x += 35;
  262.         }
  263.  
  264.         position.x += x;
  265.         position.y += y;
  266.  
  267.         const goalPosition = this._unit.room.mapManager.collisionMap.layerMap.toGlobal(position);
  268.  
  269.         this.tempSelectables.push({ selectable, x: goalPosition.x, y: goalPosition.y });
  270.     }
  271.  
  272.     private generateBodyPart(part: IPartData): PIXI.Sprite
  273.     {
  274.         if(!part) return null;
  275.  
  276.         if(this._unit.figure.isPartHidden(part.type)) return null;
  277.  
  278.         const partType = part.type === AvatarBodyPart.HAIR_BIG ? AvatarBodyPart.HAIR : part.type;
  279.        
  280.         let library = Nitro.gameManager.avatarManager.findLibrary(part.id, partType);
  281.        
  282.         if(!library) return null;
  283.  
  284.         const basePart = BaseAvatar.getPart(library.id);
  285.  
  286.         if(!basePart) return null;
  287.  
  288.         const sprite = this.generateSpriteWithActions(basePart, part);
  289.  
  290.         if(!sprite) return null;
  291.  
  292.         return sprite;
  293.     }
  294.  
  295.     private generateSpriteWithActions(basePart: BaseAvatarPart, part: IPartData): PIXI.Sprite
  296.     {
  297.         if(!basePart || !part) return null;
  298.  
  299.         let action: AvatarAction    = AvatarAction.POSTURE_STAND;
  300.         let direction: Direction    = this._direction;
  301.  
  302.         if(AvatarBuilder.HEAD_PARTS.indexOf(part.type) !== -1) direction = this._headDirection;
  303.  
  304.         if(this._posture === AvatarAction.POSTURE_WALK && AvatarBuilder.IGNORES_WALK.indexOf(part.type) !== -1) action = AvatarAction.POSTURE_STAND;
  305.  
  306.         else if(this._posture === AvatarAction.POSTURE_SIT && AvatarBuilder.IGNORES_SIT.indexOf(part.type) !== -1) action = AvatarAction.POSTURE_STAND;
  307.  
  308.         else action = this._posture;
  309.  
  310.         if(action === AvatarAction.POSTURE_LAY) direction = direction === Direction.NORTH ? Direction.SOUTH : Direction.EAST;
  311.  
  312.         if(this._gesture && AvatarBuilder.GESTURE_PARTS.indexOf(part.type) !== -1) action = this._gesture;
  313.  
  314.         if(this._expression)
  315.         {
  316.             if(AvatarBuilder.LEFT_PARTS.indexOf(part.type) !== -1)
  317.             {
  318.                 if(AvatarBuilder.EXPRESSIONS_LEFT.indexOf(this._expression) !== -1) action = this._expression;
  319.             }
  320.  
  321.             if(AvatarBuilder.RIGHT_PARTS.indexOf(part.type) !== -1)
  322.             {
  323.                 if(AvatarBuilder.EXPRESSIONS_RIGHT.indexOf(this._expression) !== -1) action = this._expression;
  324.             }
  325.         }
  326.  
  327.         if(this._carryItem)
  328.         {
  329.             const carryParts: AvatarBodyPart[] = [ AvatarBodyPart.RIGHT_HAND, AvatarBodyPart.RIGHT_SLEEVE, AvatarBodyPart.RIGHT_COAT_SLEEVE ];
  330.  
  331.             if(carryParts.indexOf(part.type) !== -1)
  332.             {
  333.                 action = this._isUsing ? AvatarAction.DRINK : AvatarAction.CARRY;
  334.             }
  335.         }
  336.  
  337.         const sprite = this.generateSprite(basePart, part, action, direction);
  338.  
  339.         if(!sprite) return null;
  340.  
  341.         return sprite;
  342.     }
  343.  
  344.     private generateSprite(basePart: BaseAvatarPart, part: IPartData, action: AvatarAction, direction: Direction): PIXI.Sprite
  345.     {
  346.         if(!basePart) return null;
  347.  
  348.         const frameIndex    = Math.floor(this.frameCount % (4 * 4) / 4);
  349.         const frameCount    = AvatarBuilder.ACTIVATES_ANIMATION.indexOf(action) !== -1 ? frameIndex : 0;
  350.  
  351.         const sprite = basePart.getSpriteFrom(BaseAvatar.AVATAR_SIZE, action, part.type, direction, frameCount, part.id);
  352.  
  353.         if(!sprite) return;
  354.  
  355.         if(direction >= Direction.SOUTH && direction <= Direction.WEST && this._expression)
  356.         {
  357.             if(AvatarBuilder.LEFT_PARTS.indexOf(part.type) !== -1 || AvatarBuilder.RIGHT_PARTS.indexOf(part.type) !== -1) sprite.scale.x = -1;
  358.         }
  359.  
  360.         if(part.colorable === 1)
  361.         {
  362.             const color = Nitro.gameManager.avatarManager.getPaletteColorFromIndex(part.setData.setType.paletteid, this._unit.figure.getColorIndexForSet(part.setData, part.colorindex));
  363.  
  364.             if(color) sprite.tint = parseInt(`0x${ color }`);
  365.         }
  366.  
  367.         if(part.type === AvatarBodyPart.EYES) sprite.tint = 0xFFFFFF;
  368.  
  369.         return sprite;
  370.     }
  371.  
  372.     public createShadow(): void
  373.     {
  374.         if(this._shadow) return;
  375.        
  376.         this.removeShadow();
  377.  
  378.         const body = BaseAvatar.getPart('hh_human_body');
  379.  
  380.         if(!body)
  381.         {
  382.             this._didCreateShadow = true;
  383.  
  384.             return;
  385.         }
  386.  
  387.         const shadowLayer = body.getSpriteFrom(BaseAvatar.AVATAR_SIZE, AvatarAction.POSTURE_STAND, AvatarBodyPart.SHADOW, Direction.NORTH, 0);
  388.  
  389.         if(!shadowLayer)
  390.         {
  391.             this._didCreateShadow = true;
  392.  
  393.             return;
  394.         }
  395.  
  396.         shadowLayer.x = 0;
  397.         shadowLayer.y = 0;
  398.  
  399.         shadowLayer.position.y = RoomConfiguration.TILE_REAL_HEIGHT;
  400.         shadowLayer.anchor.set(0.5);
  401.  
  402.         shadowLayer.alpha = 0.2;
  403.  
  404.         this._shadow = shadowLayer;
  405.  
  406.         this._didCreateShadow = true;
  407.     }
  408.  
  409.     public removeShadow(): void
  410.     {
  411.         if(!this._shadow) return;
  412.  
  413.         if(this._shadow.parent) this._shadow.parent.removeChild(this._shadow);
  414.  
  415.         this._shadow.destroy();
  416.  
  417.         this._shadow            = null;
  418.         this._didCreateShadow   = false;
  419.     }
  420.  
  421.     private setPosture(action: AvatarAction): void
  422.     {
  423.         if(!action) return;
  424.  
  425.         if(this._posture === action) return;
  426.  
  427.         this._posture = action;
  428.  
  429.         this.needsUpdate = true;
  430.     }
  431.  
  432.     public setDirection(direction: Direction): void
  433.     {
  434.         if(this._direction === direction) return;
  435.  
  436.         this._direction = direction;
  437.  
  438.         this.needsUpdate = true;
  439.     }
  440.  
  441.     public setHeadDirection(direction: Direction): void
  442.     {
  443.         if(this._headDirection === direction) return;
  444.  
  445.         this._headDirection = direction;
  446.  
  447.         this.needsUpdate = true;
  448.     }
  449.  
  450.     public gesture(gesture: AvatarAction, timeout: number): void
  451.     {
  452.         if(this._gesture === gesture) return;
  453.  
  454.         if(this._gestureTimeout) clearTimeout(this._gestureTimeout);
  455.  
  456.         this._gesture = gesture;
  457.  
  458.         this.needsUpdate = true;
  459.  
  460.         this._gestureTimeout = setTimeout(() =>
  461.         {
  462.             this._gesture = null;
  463.  
  464.             this.needsUpdate = true;
  465.         }, timeout);
  466.     }
  467.  
  468.     public expression(expression: AvatarAction, timeout: number): void
  469.     {
  470.         if(this._expression === expression) return;
  471.  
  472.         if(this._expressionTimeout) clearTimeout(this._expressionTimeout);
  473.  
  474.         this._expression = expression;
  475.  
  476.         this.needsUpdate = true;
  477.  
  478.         // this._expressionTimeout = setTimeout(() =>
  479.         // {
  480.         //     this._expression = null;
  481.  
  482.         //     this.needsUpdate = true;
  483.         // }, timeout);
  484.     }
  485.  
  486.     public carry(handItem: UnitHandItem): void
  487.     {
  488.         if(this._carryItem === handItem) return;
  489.  
  490.         this._carryItem = handItem;
  491.  
  492.         this.needsUpdate = true;
  493.  
  494.         this.startUseInterval();
  495.     }
  496.  
  497.     public startUseInterval(): void
  498.     {
  499.         if(this._useInterval) clearInterval(this._useInterval);
  500.  
  501.         if(!this._carryItem) return;
  502.  
  503.         this._useInterval = setInterval(() => this.useItem(), 5000);
  504.     }
  505.  
  506.     private useItem(): void
  507.     {
  508.         if(this._isUsing) return;
  509.  
  510.         if(!this._carryItem)
  511.         {
  512.             this._isUsing = false;
  513.  
  514.             this.needsUpdate = true;
  515.  
  516.             if(this._useInterval) clearInterval(this._useInterval);
  517.  
  518.             return;
  519.         }
  520.  
  521.         this._isUsing = true;
  522.  
  523.         this.needsUpdate = true;
  524.  
  525.         setTimeout(() =>
  526.         {
  527.             if(!this._carryItem) return;
  528.  
  529.             this._isUsing = false;
  530.  
  531.             this.needsUpdate = true;
  532.         }, 2000);
  533.     }
  534.  
  535.     public get unit(): Unit
  536.     {
  537.         return this._unit;
  538.     }
  539. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement