Ticket #2357: idle_worker_blink_v8.2.patch
File idle_worker_blink_v8.2.patch, 23.0 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/public/gui/common/colorFades.js
1 1 /* 2 DESCRIPTION : Some functions to make colo ur fades on GUI elements (f.e. used for hero and group icons)2 DESCRIPTION : Some functions to make color fades on GUI elements (f.e. used for hero and group icons) 3 3 NOTES : 4 4 */ 5 5 6 // Used for storing object names of running color fades in order to stop them, if the fade is restarted before the old ended 7 var g_colorFade = {}; 8 g_colorFade["id"] = {}; 9 g_colorFade["tick"] = {}; 6 // Used for storing information about color fades 7 var g_colorFade = {}; 10 8 11 9 /** 12 * starts fading a colour of a GUI object using the sprite argument 13 * name: name of the object which colour should be faded 14 * changeInterval: interval in ms when the next colour change should be made 15 * duration: maximal duration of the complete fade 16 * colour: RGB + opacity object with keys r,g,b and o 10 * returns the init RGB color setting 11 */ 12 function getInitColorFadeRGB() 13 { 14 var rgb = {}; 15 rgb.r = 0; 16 rgb.g = 0; 17 rgb.b = 0; 18 rgb.o = 100; 19 return rgb; 20 } 21 22 /** 23 * starts fading a color of a GUI object using the sprite argument 24 * name: name of the object which color should be faded 25 * tickInterval: interval in ms when the next color change should be made 26 * duration: maximal duration of the complete fade (if 0 it runs until it is stopped) 17 27 * fun_colorTransform: function which transform the colors; 18 * arguments: [colour object, tickCounter] 28 * arguments: [var data] 29 * restartAble [optional: if false, the fade can not be restarted; default: true 19 30 * fun_smoothRestart [optional]: a function, which returns a smooth tick counter, if the fade should be started; 20 * arguments: [tickCounter of current fade; not smaller than 1 or it restarts at 0] returns: smooth tick counter value 21 * tickCounter [optional]: should not be set by hand! - how often the function was called recursively 31 * arguments: [var data]; must return false, if smooth restart was not possible and true, if it was ok 22 32 */ 23 function fadeColour(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, tickCounter)33 function startColorFade(name, tickInterval, duration, fun_colorTransform, restartAble, fun_smoothRestart) // TODO: replace restartAble = true, fun_smoothRestart = null when it is supported (spiderMonkey upgrade #1886) 24 34 { 25 35 // get the overlay 26 36 var overlay = Engine.GetGUIObjectByName(name); … … 28 38 return; 29 39 30 40 // check, if fade overlay was started just now 31 if (! tickCounter)41 if (!isColorFadeRunning(name)) 32 42 { 33 tickCounter = 1;34 43 overlay.hidden = false; 35 36 // check, if another animation is running and restart it, if it's the case 37 if (isColourFadeRunning(name)) 38 { 39 restartColourFade(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, g_colorFade.tick[name]); 40 return; 41 } 44 45 // store the values into a var to make it more flexible (can be changed from every function) 46 var data = {}; 47 data.timerId = -1; 48 data.tickInterval = tickInterval; 49 data.duration = duration; 50 data.fun_colorTransform = fun_colorTransform; 51 data.restartAble = restartAble !== false; // TODO: ' !== false' and add default parameter 52 data.fun_smoothRestart = fun_smoothRestart; 53 data.tickCounter = 0; 54 data.runsUntilStop = duration == 0; 55 data.stopFade = false; 56 data.rgb = getInitColorFadeRGB(); 57 58 // store it! 59 g_colorFade[name] = data; 60 61 // start with fading 62 fadeColorTick(name); 42 63 } 64 else if (restartAble) 65 { 66 restartColorFade(name, tickInterval, duration, fun_colorTransform, restartAble, fun_smoothRestart); 67 return; 68 } 69 } 70 71 /** 72 * makes the color changes in a tick 73 * name: name of the object which color should be faded 74 */ 75 function fadeColorTick(name) 76 { 77 // make some checks 78 if (!isColorFadeRunning(name)) 79 return; 80 81 var overlay = Engine.GetGUIObjectByName(name); 82 if (!overlay) 83 return; 84 var data = g_colorFade[name]; 85 86 // change the color 87 data.fun_colorTransform(data); 43 88 44 // get colors 45 fun_colorTransform(colour, tickCounter); 46 47 // set new colour 48 overlay.sprite="colour: "+colour.r+" "+colour.g+" "+colour.b+" "+colour.o; 89 // set new color 90 var rgb = data.rgb; 91 overlay.sprite="colour: "+rgb.r+" "+rgb.g+" "+rgb.b+" "+rgb.o; 49 92 50 93 // recusive call, if duration is positive 51 duration-= changeInterval; 52 if (duration > 0 && colour.o > 0) 94 if (!data.stopFade && (data.runsUntilStop || data.duration - (data.tickInterval * data.tickCounter) > 0)) 53 95 { 54 var id = setTimeout(function() { fadeColo ur(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, ++tickCounter); }, changeInterval);55 g_colorFade.id[name]= id;56 g_colorFade.tick[name] = tickCounter;96 var id = setTimeout(function() { fadeColorTick(name); }, data.tickInterval); 97 data.timerId = id; 98 data.tickCounter++; 57 99 } 58 100 else 59 101 { 60 102 overlay.hidden = true; 61 stopColo urFade(name);103 stopColorFade(name); 62 104 } 63 105 } 64 106 65 66 107 /** 67 * checks, if a colo ur fade on that object is running68 * name: name of the object which colo ur fade should be checked108 * checks, if a color fade on that object is running 109 * name: name of the object which color fade should be checked 69 110 * return: true a running fade was found 70 111 */ 71 function isColo urFadeRunning(name)112 function isColorFadeRunning(name) 72 113 { 73 return name in g_colorFade .id;114 return name in g_colorFade; 74 115 } 75 116 76 117 /** 77 * stops fading a colo ur78 * name: name of the object which colo ur fade should be stopped79 * hideOverlay : hides the overlay, if true118 * stops fading a color 119 * name: name of the object which color fade should be stopped 120 * hideOverlay [optional]: hides the overlay, if true [default: true] 80 121 * return: true a running fade was stopped 81 122 */ 82 function stopColo urFade(name, hideOverlay)123 function stopColorFade(name, hideOverlay) //TODO: add 'hideOverlay = true' when its supported (spiderMonkey upgrade #1886) 83 124 { 84 // check, if a colo ur fade is running85 if (!isColo urFadeRunning(name))125 // check, if a color fade is running 126 if (!isColorFadeRunning(name)) 86 127 return false; 87 128 88 129 // delete the timer 89 clearTimeout(g_colorFade .id[name]);90 delete g_colorFade .id[name];91 delete g_colorFade.tick[name]; 92 130 clearTimeout(g_colorFade[name].timerId); 131 delete g_colorFade[name]; 132 133 hideOverlay = hideOverlay !== false; // TODO: remove this line and add default value for hideOverlay 93 134 // get the overlay and hide it 94 135 if (hideOverlay) 95 136 { 96 137 var overlay = Engine.GetGUIObjectByName(name); 97 if (overlay)138 if (overlay) 98 139 overlay.hidden = true; 99 140 } 100 141 return true; … … 101 142 } 102 143 103 144 /** 104 * restarts a colo ur fade105 * see paramter in fadeColourfunction145 * restarts a color fade 146 * see paramter in startColorFade function 106 147 */ 107 function restartColo urFade(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, tickCounter)148 function restartColorFade(name) 108 149 { 109 // check, if a colo ur fade is running110 if (!isColo urFadeRunning(name))150 // check, if a color fade is running 151 if (!isColorFadeRunning(name)) 111 152 return false; 112 153 154 var data = g_colorFade[name]; 113 155 // check, if fade can be restarted smoothly 114 if ( fun_smoothRestart)156 if (data.fun_smoothRestart) 115 157 { 116 tickCounter = fun_smoothRestart(colour, tickCounter); 117 // set new function to existing timer 118 var fun = function() { fadeColour(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, tickCounter); }; 119 setNewTimerFunction(g_colorFade.id[name], fun); 158 // if call was too late 159 if (!data.fun_smoothRestart(data)) 160 { 161 data.rgb = getInitColorFadeRGB(); // set RGB start values 162 data.tickCounter = 0; 163 } 120 164 } 121 165 // stop it and restart it 122 166 else 123 167 { 124 stopColo urFade(name, true);125 fadeColour(name, changeInterval, duration, colour, fun_colorTransform);168 stopColorFade(name, false); 169 startColorFade(name, data.changeInterval, data.duration, data.fun_colorTransform, data.restartAble, data.fun_smoothRestart); 126 170 } 127 171 return true; 128 172 } … … 133 177 134 178 var g_fadeAttackUnit = {}; 135 179 g_fadeAttackUnit.blinkingTicks = 50; // how many ticks should first blinking phase be 136 g_fadeAttackUnit.blinkingChangeInterval = 5; // how often should the colo ur be changed during the blinking phase137 g_fadeAttackUnit.gb ColourChangeRate = 3; // how fast should blue and green part of the colour change180 g_fadeAttackUnit.blinkingChangeInterval = 5; // how often should the color be changed during the blinking phase 181 g_fadeAttackUnit.gbcolorChangeRate = 3; // how fast should blue and green part of the color change 138 182 g_fadeAttackUnit.fadeOutStart = 100; // when should the fade out start using the opacity 139 183 g_fadeAttackUnit.opacityChangeRate = 3; // how fast should opacity change 140 184 141 /** 142 * rgb: colour object with keys r,g,b and o 143 * tickCounter: how often the fade was executed 144 */ 145 function colourFade_attackUnit(rgb, tickCounter) 185 function colorFade_attackUnit(data) 146 186 { 187 var rgb = data.rgb; 188 189 // init color 190 if (data.tickCounter == 0) 191 rgb.r = 175; 147 192 // blinking 148 if ( tickCounter < g_fadeAttackUnit.blinkingTicks)193 if (data.tickCounter < g_fadeAttackUnit.blinkingTicks) 149 194 { 150 195 // slow that process down 151 if ( tickCounter % g_fadeAttackUnit.blinkingChangeInterval != 0)196 if (data.tickCounter % g_fadeAttackUnit.blinkingChangeInterval != 0) 152 197 return; 153 198 154 rgb.g = rgb.g == 0 ? 255 : rgb.g = 0; 155 rgb.b = rgb.b == 0 ? 255 : rgb.b = 0; 199 rgb.g = rgb.g == 0 ? 255 : 0; 156 200 } 157 // wait a short time and then colo ur fade from red to grey to nothing158 else if ( tickCounter >= g_fadeAttackUnit.blinkingTicks + g_fadeAttackUnit.blinkingChangeInterval)201 // wait a short time and then color fade from red to grey to nothing 202 else if ( data.tickCounter >= g_fadeAttackUnit.blinkingTicks + g_fadeAttackUnit.blinkingChangeInterval) 159 203 { 160 rgb.g = rgb.g < 255 ? rgb.g += g_fadeAttackUnit.gbColourChangeRate * Math.sqrt(tickCounter - g_fadeAttackUnit.blinkingTicks) : 255; 161 rgb.b = rgb.g; 204 rgb.g = rgb.g < 255 ? rgb.g += g_fadeAttackUnit.gbcolorChangeRate * Math.sqrt(data.tickCounter - g_fadeAttackUnit.blinkingTicks) : 255; 162 205 163 206 // start with fading it out 164 207 if (rgb.g > g_fadeAttackUnit.fadeOutStart) 165 208 rgb.o = rgb.o > g_fadeAttackUnit.opacityChangeRate ? rgb.o -= g_fadeAttackUnit.opacityChangeRate : 0; 209 // check for end 210 if (rgb.o == 0) 211 data.stopFade = true; 166 212 } 213 rgb.b = rgb.g; 167 214 } 168 215 169 /** 170 * makes a smooth fade, if the attack on the unit has not stopped yet 171 * rgb: colour object with keys r,g,b and o 172 * tickCounter: how often the fade was executed 173 */ 174 function smoothColourFadeRestart_attackUnit(rgb, tickCounter) 216 function smoothColorFadeRestart_attackUnit(data) 175 217 { 176 218 // check, if in blinking phase 177 if ( tickCounter < g_fadeAttackUnit.blinkingTicks)219 if (data.tickCounter < g_fadeAttackUnit.blinkingTicks) 178 220 { 179 // get rgb to current state 180 for (var i = 1; i <= tickCounter; i++) 181 colourFade_attackUnit(rgb, i); 182 // set the tick counter back to start 183 return (tickCounter % (g_fadeAttackUnit.blinkingChangeInterval * 2)) + 1; 221 data.tickCounter = data.tickCounter % (g_fadeAttackUnit.blinkingChangeInterval * 2); 222 data.rgb.o = getInitColorFadeRGB().o; 223 return true; 184 224 } 185 return 1;225 return false; 186 226 } 187 227 188 //[END] of hero fade functions 189 No newline at end of file 228 //[END] of hero fade functions 229 //[START] idle workers icon 230 231 function colorFade_IdleWorker(data) 232 { 233 var rgb = data.rgb; 234 // init color 235 if (data.tickCounter == 0) 236 { 237 rgb.r = 255; 238 rgb.g = 255; 239 rgb.b = 255; 240 } 241 // hide it every tick 242 if (data.tickCounter % 2 == 0) 243 rgb.o = 0; 244 else 245 rgb.o = 100; 246 } 247 248 //[END] of idle workers icon functions 249 No newline at end of file -
binaries/data/mods/public/gui/session/session.js
56 56 // always through the list of all ongoing attacks... 57 57 var g_previousHeroHitPoints = undefined; 58 58 59 // cache idle worker button class names 60 var g_idleWorkerClasses = undefined; 61 59 62 function GetSimState() 60 63 { 61 64 if (!g_SimState) … … 148 151 { 149 152 g_Players = getPlayerData(null); 150 153 } 154 // cache worker class data 155 g_idleWorkerClasses = Engine.GuiInterfaceCall("GetIdleWorkerClasses"); 151 156 152 157 // Cache civ data 153 158 g_CivData = loadCivData(); … … 486 491 487 492 updateHero(); 488 493 updateGroups(); 494 updateIdleWorkerButton(); 489 495 updateDebug(); 490 496 updatePlayerDisplay(); 491 497 updateSelectionDetails(); … … 499 505 if (battleState) 500 506 global.music.setState(global.music.states[battleState]); 501 507 508 }; 509 510 /** 511 * updates the idle worker button 512 */ 513 function updateIdleWorkerButton() 514 { 515 var simState = GetSimState(); 516 var idleUnitsCounter = simState.players[Engine.GetPlayerID()].idleWorkerButtonCount; 517 // set color fade and label 518 if (idleUnitsCounter > 0) 519 { 520 startColorFade("idleWorkerOverlay", 750, 0, colorFade_IdleWorker, false); 521 var label = Engine.GetGUIObjectByName("idleWorkerLabel") 522 label.caption = idleUnitsCounter; 523 label.hidden = false; 524 } 525 else 526 { 527 stopColorFade("idleWorkerOverlay"); 528 var label = Engine.GetGUIObjectByName("idleWorkerLabel"); 529 label.hidden = true; 530 } 502 531 } 503 532 504 533 /** 534 * finds an idle worker when the idle worker button is clicked 535 */ 536 function findIdleWorker() 537 { 538 findIdleUnit(g_idleWorkerClasses); 539 } 540 541 542 /** 505 543 * updates a status bar on the GUI 506 544 * nameOfBar: name of the bar 507 545 * points: points to show … … 595 633 { 596 634 g_previousHeroHitPoints = heroState.hitpoints; 597 635 // trigger the animation 598 fadeColour("heroHitOverlay", 100, 10000, {"r": 175,"g": 0,"b": 0,"o": 100}, colourFade_attackUnit, smoothColourFadeRestart_attackUnit);636 startColorFade("heroHitOverlay", 100, 0, colorFade_attackUnit, true, smoothColorFadeRestart_attackUnit); 599 637 return; 600 638 } 601 639 } -
binaries/data/mods/public/gui/session/session.xml
953 953 <object type="button" 954 954 style="iconButton" 955 955 tooltip_style="sessionToolTip" 956 tooltip="Find idle worker" 957 hotkey="selection.idleworker" 958 > 959 <!-- TODO: should highlight the button if there's non-zero idle workers --> 960 <object size="0 0 100% 100%" type="image" sprite="idleWorker" ghost="true" /> 961 <action on="Press">findIdleUnit(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action> 962 </object> 956 tooltip="Find idle worker" 957 hotkey="selection.idleworker" 958 > 959 <object size="0 0 100% 100%" type="image" sprite="idleWorker" ghost="true" /> 960 <object name="idleWorkerOverlay" hidden="true" type="image" ghost="true" size="2 2 100%-2 100%-2"/> 961 <object name="idleWorkerLabel" type="text" style="groupIconsText" size="0 0 100% 100%" ghost="true"/> 962 <action on="Press">findIdleWorker();</action> 963 </object> 963 964 </object> 964 </object>965 </object> 965 966 966 967 <!-- ================================ ================================ --> 967 968 <!-- Supplemental Details Panel (Left of Selection Details) --> -
binaries/data/mods/public/simulation/components/GuiInterface.js
89 89 "team": cmpPlayer.GetTeam(), 90 90 "teamsLocked": cmpPlayer.GetLockTeams(), 91 91 "cheatsEnabled": cmpPlayer.GetCheatsEnabled(), 92 "idleWorkerButtonCount": cmpPlayer.GetIdleWorkerButtonCount(), 92 93 "phase": phase, 93 94 "isAlly": allies, 94 95 "isMutualAlly": mutualAllies, … … 728 729 } 729 730 730 731 // Returns the battle state of the player. 732 GuiInterface.prototype.GetIdleWorkerClasses = function(player) 733 { 734 // try to get the data 735 var cmpPlayer = QueryPlayerIDInterface(player, IID_Player); 736 if (!cmpPlayer) 737 return []; 738 else 739 return cmpPlayer.GetIdleWorkerButtonClassesList(); 740 }; 741 742 // Returns the battle state of the player. 731 743 GuiInterface.prototype.GetBattleState = function(player) 732 744 { 733 745 var cmpBattleDetection = QueryPlayerIDInterface(player, IID_BattleDetection); … … 1977 1989 "SetWallPlacementPreview": 1, 1978 1990 "GetFoundationSnapData": 1, 1979 1991 "PlaySound": 1, 1992 "GetIdleWorkerClasses" :1, 1980 1993 "FindIdleUnits": 1, 1981 1994 "GetTradingRouteGain": 1, 1982 1995 "GetTradingDetails": 1, -
binaries/data/mods/public/simulation/components/Player.js
1 1 function Player() {} 2 2 3 3 Player.prototype.Schema = 4 "<a:component type='system'/><empty/>"; 5 4 "<element name='IdleWorkerButtonClasses' a:help='Classes of entities which are used for the idle worker button.'>" + 5 "<attribute name='datatype'>" + 6 "<value>tokens</value>" + 7 "</attribute>" + 8 "<text/>" + 9 "</element>"; 10 6 11 Player.prototype.Init = function() 7 12 { 8 13 this.playerID = undefined; … … 37 42 this.cheatsEnabled = false; 38 43 this.cheatTimeMultiplier = 1; 39 44 this.heroes = []; 45 this.idleWorkerButtonCount = 0; 46 this.idleWorkerButtonClasses = this.template.IdleWorkerButtonClasses._string ? this.template.IdleWorkerButtonClasses._string.split(/\s+/) : []; // classes used for the work idle button 40 47 Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager).CheckConquestCriticalEntities(); 41 48 }; 42 49 50 /** 51 * Returns an array of unit classes which are used for the idle worker button 52 */ 53 Player.prototype.GetIdleWorkerButtonClassesList = function() 54 { 55 return this.idleWorkerButtonClasses; 56 }; 57 43 58 Player.prototype.SetPlayerID = function(id) 44 59 { 45 60 this.playerID = id; … … 560 575 if (index >= 0) 561 576 this.heroes.splice(index, 1); 562 577 } 578 // check, if new idle worker is gone 579 var cmpUnitAI = Engine.QueryInterface(msg.entity, IID_UnitAI); 580 if (cmpUnitAI) 581 if (cmpUnitAI.IsIdle() && cmpUnitAI.IsUsedForIdleWorkerButton()) 582 this.DecreaseWorkerButtonCount(); 563 583 } 564 584 if (msg.to == this.playerID) 565 585 { … … 571 591 572 592 if (cmpIdentity && cmpIdentity.HasClass("Hero")) 573 593 this.heroes.push(msg.entity); 594 595 // check, if new idle worker is there 596 var cmpUnitAI = Engine.QueryInterface(msg.entity, IID_UnitAI); 597 if (cmpUnitAI) 598 if (cmpUnitAI.IsIdle() && cmpUnitAI.IsUsedForIdleWorkerButton()) 599 this.IncreaseWorkerButtonCount(); 574 600 } 575 601 }; 576 602 … … 664 690 cmpGUIInterface.PushNotification(notification); 665 691 }; 666 692 693 Player.prototype.GetIdleWorkerButtonCount = function() 694 { 695 return this.idleWorkerButtonCount; 696 }; 697 698 Player.prototype.IncreaseWorkerButtonCount = function() 699 { 700 this.idleWorkerButtonCount++; 701 }; 702 703 Player.prototype.DecreaseWorkerButtonCount = function() 704 { 705 this.idleWorkerButtonCount--; 706 if (this.idleWorkerButtonCount < 0) 707 { 708 this.idleWorkerButtonCount = 0; 709 error("Negative worker idle count for player '" + this.playerID + "'"); 710 } 711 }; 712 667 713 Engine.RegisterComponentType(IID_Player, "Player", Player); -
binaries/data/mods/public/simulation/components/UnitAI.js
169 169 "GuardedAttacked": function(msg) { 170 170 // ignore 171 171 }, 172 173 "UnitIdleChanged": function(msg) { 174 // do only if its not animal and is used for the idle worker button 175 if (!this.IsAnimal() && this.IsUsedForIdleWorkerButton()) 176 { 177 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 178 if (cmpPlayer) 179 { 180 if(msg.idle) 181 cmpPlayer.IncreaseWorkerButtonCount(); 182 else 183 cmpPlayer.DecreaseWorkerButtonCount(); 184 } 185 } 186 }, 172 187 173 188 // Formation handlers: 174 189 … … 1139 1154 1140 1155 // Stop moving as soon as the formation disbands 1141 1156 this.StopMoving(); 1157 1158 // if unit is dead, stop here 1159 if (!msg.isAlive) 1160 return; 1142 1161 1143 1162 // If the controller handled an order but some members rejected it, 1144 1163 // they will have no orders and be in the FORMATIONMEMBER.IDLE state. … … 3052 3071 this.formationController = INVALID_ENTITY; // entity with IID_Formation that we belong to 3053 3072 this.isGarrisoned = false; 3054 3073 this.isIdle = false; 3074 this.isUsedForIdleWorkerButton = undefined; // will be initialised, if IsUsedForIdleWorkerButton() is called the first time 3055 3075 this.lastFormationTemplate = ""; 3056 3076 this.finishedOrder = false; // used to find if all formation members finished the order 3057 3077 … … 3130 3150 return Engine.QueryInterface(this.entity, IID_Heal); 3131 3151 }; 3132 3152 3153 UnitAI.prototype.IsUsedForIdleWorkerButton = function() 3154 { 3155 // return cached value, if some is stored 3156 if (this.isUsedForIdleWorkerButton !== undefined) 3157 return this.isUsedForIdleWorkerButton; 3158 3159 // calculate value 3160 this.isUsedForIdleWorkerButton = false; 3161 var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); 3162 if (!cmpIdentity) 3163 return false; 3164 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 3165 if (!cmpPlayer) 3166 return false; 3167 // check idle class names 3168 for each(var className in cmpPlayer.GetIdleWorkerButtonClassesList()) 3169 if (cmpIdentity.HasClass(className)) { 3170 this.isUsedForIdleWorkerButton = true; 3171 break; 3172 } 3173 // return the value 3174 return this.isUsedForIdleWorkerButton; 3175 }; 3176 3133 3177 UnitAI.prototype.IsIdle = function() 3134 3178 { 3135 3179 return this.isIdle; … … 3772 3816 UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed}); 3773 3817 }; 3774 3818 3819 UnitAI.prototype.OnUnitIdleChanged = function(msg) 3820 { 3821 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 3822 if (!cmpOwnership) 3823 return; 3824 UnitFsm.ProcessMessage(this, {"type": "UnitIdleChanged", "idle": msg.idle, "player": cmpOwnership.GetOwner()}); 3825 } 3826 3775 3827 //// Helper functions to be called by the FSM //// 3776 3828 3777 3829 UnitAI.prototype.GetWalkSpeed = function() … … 4521 4573 } 4522 4574 4523 4575 // If we were removed from a formation, let the FSM switch back to INDIVIDUAL 4576 // but only, if unit is not dead 4524 4577 if (ent == INVALID_ENTITY) 4525 UnitFsm.ProcessMessage(this, { "type": "FormationLeave" }); 4578 { 4579 var cmpHealth = Engine.QueryInterface(this.entity, IID_Health); 4580 if (!cmpHealth) 4581 return; 4582 UnitFsm.ProcessMessage(this, { "type": "FormationLeave", "isAlive": cmpHealth.GetHitpoints() > 0 }); 4583 } 4526 4584 }; 4527 4585 4528 4586 UnitAI.prototype.GetFormationController = function() -
binaries/data/mods/public/simulation/templates/special/player.xml
38 38 </Pillar> 39 39 </LimitChangers> 40 40 </EntityLimits> 41 <Player/> 41 <Player> 42 <IdleWorkerButtonClasses datatype="tokens">Worker Trade FishingBoat</IdleWorkerButtonClasses> 43 </Player> 42 44 <StatisticsTracker/> 43 45 <TechnologyManager/> 44 46 </Entity>