Ticket #2154: patch_townbell.diff

File patch_townbell.diff, 20.2 KB (added by Itms, 11 years ago)
  • binaries/data/mods/public/art/textures/ui/session/icons/bell_level0.png

    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
  • binaries/data/mods/public/art/textures/ui/session/icons/bell_level1.png

    Property changes on: binaries/data/mods/public/art/textures/ui/session/icons/bell_level0.png
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +application/octet-stream
    \ No newline at end of property
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
  • binaries/data/mods/public/art/textures/ui/session/icons/bell_level2.png

    Property changes on: binaries/data/mods/public/art/textures/ui/session/icons/bell_level1.png
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +application/octet-stream
    \ No newline at end of property
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
  • binaries/data/mods/public/gui/session/input.js

    Property changes on: binaries/data/mods/public/art/textures/ui/session/icons/bell_level2.png
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +application/octet-stream
    \ No newline at end of property
     
    18411841            case "back-to-work":
    18421842                backToWork();
    18431843                break;
     1844            case "ring-town-bell-yellow":
     1845                ringYellowAlert();
     1846                break;
     1847            case "ring-town-bell-red":
     1848                ringRedAlert();
     1849                break;
     1850            case "ring-town-bell-end":
     1851                ringEndOfAlert();
     1852                break;
    18441853            default:
    18451854                break;
    18461855            }
     
    21152124   
    21162125}
    21172126
     2127function ringYellowAlert()
     2128{
     2129    var strikers = g_Selection.toList().filter(function(e) {
     2130        var state = GetEntityState(e);
     2131        if (state && state.townBellStriker && state.townBellStriker.level == "End")
     2132            return true;
     2133        return false;
     2134    });
     2135   
     2136    Engine.PostNetworkCommand({"type": "ring-town-bell-yellow", "strikers": strikers});
     2137}
     2138
     2139function ringRedAlert()
     2140{
     2141    var strikers = g_Selection.toList().filter(function(e) {
     2142        var state = GetEntityState(e);
     2143        if (state && state.townBellStriker && state.townBellStriker.level == "Yellow")
     2144            return true;
     2145        return false;
     2146    });
     2147   
     2148    Engine.PostNetworkCommand({"type": "ring-town-bell-red", "strikers": strikers});   
     2149}
     2150
     2151function ringEndOfAlert()
     2152{
     2153    var strikers = g_Selection.toList().filter(function(e) {
     2154        var state = GetEntityState(e);
     2155        if (state && state.townBellStriker && (state.townBellStriker.level == "Yellow" || state.townBellStriker.level == "Red"))
     2156            return true;
     2157        return false;
     2158    });
     2159   
     2160    Engine.PostNetworkCommand({"type": "ring-town-bell-end", "strikers": strikers});   
     2161}
     2162
    21182163function clearSelection()
    21192164{
    21202165    if(inputState==INPUT_BUILDING_PLACEMENT || inputState==INPUT_BUILDING_WALL_PATHING)
  • binaries/data/mods/public/gui/session/utility_functions.js

     
    302302            "icon": "production.png"
    303303        });
    304304    }
     305   
     306    if(entState.townBellStriker)
     307    {
     308        switch(entState.townBellStriker.level)
     309        {
     310            case "End":
     311                commands.push({
     312                    "name": "ring-town-bell-yellow",
     313                    "tooltip": "Town Bell : Garrison all female citizens in the first nearby building",
     314                    "icon": "bell_level1.png"
     315                });
     316                break;
     317            case "Yellow":
     318                commands.push({
     319                    "name": "ring-town-bell-red",
     320                    "tooltip": "Red Alert : Garrison also the citizen-soldiers",
     321                    "icon": "bell_level2.png"
     322                });
     323                commands.push({
     324                    "name": "ring-town-bell-end",
     325                    "tooltip": "End of Alert",
     326                    "icon": "bell_level0.png"
     327                });
     328                break;
     329            case "Red":
     330                commands.push({
     331                    "name": "ring-town-bell-end",
     332                    "tooltip": "End of Alert",
     333                    "icon": "bell_level0.png"
     334                });
     335                break;
     336            default:
     337                break;
     338        }
     339    }
    305340
    306341    return commands;
    307342}
  • binaries/data/mods/public/simulation/components/GarrisonHolder.js

     
    261261
    262262/**
    263263 * Ejects units and orders them to move to the Rally Point.
     264 * If a unit was garrisoned by a Town Bell and remembers any work, sends it back to this work.
    264265 * Returns true if successful, false if not
    265266 */
    266267GarrisonHolder.prototype.PerformEject = function(entities, forced)
     
    268269    if (!this.IsGarrisoningAllowed() && !forced)
    269270        return false;
    270271
    271     var ejectedEntities = [];
     272    var ejectedEntities = [];   
     273    var workers = [];
     274    var nonWorkers = [];
    272275    var success = true;
    273276    for each (var entity in entities)
    274277    {
     278        // Filter the units who shall go back to work after a Town Bell
     279        var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
     280        if (cmpUnitAI && cmpUnitAI.GetTownBellStriker() && cmpUnitAI.GetLastWorkOrder())
     281            workers.push(entity);
     282        else
     283            nonWorkers.push(entity);
     284       
    275285        if (this.Eject(entity, forced))
    276286        {
    277287            var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     
    282292        else
    283293            success = false;
    284294    }
    285 
    286     this.OrderWalkToRallyPoint(ejectedEntities);
     295   
     296    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     297    ProcessCommand(cmpOwnership.GetOwner(), {"type": "back-to-work", "workers": workers});
     298   
     299    this.OrderWalkToRallyPoint(nonWorkers);
     300   
    287301    this.UpdateGarrisonFlag();
    288302
    289303    return success;
     
    291305
    292306/**
    293307 * Unload unit from the garrisoning entity and order them
    294  * to move to the Rally Point
     308 * to move to the Rally Point (or to its work after a Town Bell)
    295309 * Returns true if successful, false if not
    296310 */
    297311GarrisonHolder.prototype.Unload = function(entity, forced)
     
    301315
    302316/**
    303317 * Unload one or all units that match a template and owner from
    304  * the garrisoning entity and order them to move to the Rally Point
     318 * the garrisoning entity and order them to move to the Rally Point (or to their work after a Town Bell)
    305319 * Returns true if successful, false if not
    306320 *
    307321 * extendedTemplate has the format "p"+ownerid+"&"+template
     
    342356
    343357/**
    344358 * Unload all units with same owner as the entity
    345  * and order them to move to the Rally Point
     359 * and order them to move to the Rally Point (or to their work after a Town Bell)
    346360 * Returns true if all successful, false if not
    347361 */
    348362GarrisonHolder.prototype.UnloadAllOwn = function(forced)
     
    366380
    367381/**
    368382 * Unload all units from the entity
    369  * and order them to move to the Rally Point
     383 * and order them to move to the Rally Point (or to their work after a Town Bell)
    370384 * Returns true if all successful, false if not
    371385 */
    372386GarrisonHolder.prototype.UnloadAll = function(forced)
     
    376390};
    377391
    378392/**
     393 * Unload all units garrisoned by the TownBellStriker striker
     394 * and order them to move to the Rally Point (or to their work)
     395 * Returns true if all successful, false if not
     396 */
     397GarrisonHolder.prototype.UnloadAllTownBell = function(striker, forced)
     398{
     399    var entities = [];
     400    for each (var entity in this.entities)
     401    {
     402        var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
     403        if (cmpUnitAI && cmpUnitAI.GetTownBellStriker() == striker)
     404            entities.push(entity);
     405    }
     406   
     407    return this.PerformEject(entities, forced);
     408};
     409
     410/**
    379411 * Used to check if the garrisoning entity's health has fallen below
    380412 * a certain limit after which all garrisoned units are unloaded
    381413 */
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    377377            "healableClasses": cmpHeal.GetHealableClasses(),
    378378        };
    379379    }
     380   
     381    var cmpTownBellStriker = Engine.QueryInterface(ent, IID_TownBellStriker);
     382    if(cmpTownBellStriker)
     383    {
     384        ret.townBellStriker = {
     385            "level": cmpTownBellStriker.GetLevel(),
     386        };
     387    }
    380388
    381389    ret.visibility = cmpRangeManager.GetLosVisibility(ent, player, false);
    382390
  • binaries/data/mods/public/simulation/components/TownBellStriker.js

     
     1function TownBellStriker() {}
     2
     3TownBellStriker.prototype.Schema = "<element name='Range'><data type='nonNegativeInteger'/></element>";
     4
     5TownBellStriker.prototype.Init = function()
     6{
     7    this.level = "End";
     8};
     9
     10TownBellStriker.prototype.GetLevel = function()
     11{
     12    return this.level;
     13};
     14
     15TownBellStriker.prototype.RingYellowAlert = function()
     16{   
     17    // Find units owned by this unit's player
     18    var players = [];
     19    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     20    if (cmpOwnership)
     21        players.push(cmpOwnership.GetOwner());
     22   
     23    var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
     24    var units = rangeMan.ExecuteQuery(this.entity, 0, this.template.Range, players, IID_UnitAI).filter( function(e){
     25        var cmpIdentity = Engine.QueryInterface(e, IID_Identity);
     26        return (cmpIdentity && cmpIdentity.HasClass("Female"));
     27        });
     28       
     29    this.level = "Yellow"; 
     30   
     31    for each(unit in units)
     32    {
     33        var cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI);
     34        cmpUnitAI.AddOrder("TownBell", {"striker": this.entity}, false);
     35    }
     36   
     37    return true;
     38};
     39
     40TownBellStriker.prototype.RingRedAlert = function()
     41{
     42    // Find units owned by this unit's player
     43    var players = [];
     44    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     45    if (cmpOwnership)
     46        players.push(cmpOwnership.GetOwner());
     47   
     48    // If a yellow alert has already been struck, only give orders to the units who don't already have orders.
     49    var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
     50    var units = rangeMan.ExecuteQuery(this.entity, 0, this.template.Range, players, IID_UnitAI).filter( function(e){
     51        var cmpIdentity = Engine.QueryInterface(e, IID_Identity);
     52        var cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI);
     53        return (cmpIdentity && (cmpIdentity.HasClass("Female") || cmpIdentity.HasClass("CitizenSoldier"))
     54            && !cmpUnitAI.GetTownBellStriker()
     55            );
     56        });
     57       
     58    this.level = "Red";
     59   
     60    for each(unit in units)
     61    {
     62        var cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI);
     63        cmpUnitAI.AddOrder("TownBell", {"striker": this.entity}, false);
     64    }
     65   
     66    return true;
     67};
     68
     69TownBellStriker.prototype.RingEndOfAlert = function()
     70{
     71    // Find buildings owned by this unit's player
     72    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     73    if (cmpOwnership)
     74        var player = cmpOwnership.GetOwner();
     75    else
     76        return false;
     77   
     78    var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
     79    var holders = rangeMan.GetEntitiesByPlayer(player).filter( function(e) {
     80        var cmpGarrisonHolder = Engine.QueryInterface(e, IID_GarrisonHolder);
     81        if (cmpGarrisonHolder)
     82            return true;
     83        return false;
     84    });
     85   
     86    this.level = "End";
     87   
     88    for each(holder in holders)
     89    {
     90        var cmpGarrisonHolder = Engine.QueryInterface(holder, IID_GarrisonHolder);
     91        cmpGarrisonHolder.UnloadAllTownBell(this.entity, true);
     92    }
     93   
     94    return true;
     95};
     96
     97TownBellStriker.prototype.Deinit = function()
     98{
     99   
     100};
     101
     102TownBellStriker.prototype.OnUpdate = function(msg)
     103{
     104   
     105};
     106
     107Engine.RegisterComponentType(IID_TownBellStriker, "TownBellStriker", TownBellStriker);
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    620620        }
    621621    },
    622622
     623    "Order.TownBell": function(msg) {
     624        this.townBellStriker = this.order.data.striker;
     625       
     626        // Find a target to garrison into, if we don't already have one
     627        if(!this.garrisoningTarget)
     628        {
     629            var nearby = this.FindNearbyGarrisonHolder();
     630            if (nearby)
     631                this.garrisoningTarget = nearby;
     632            else
     633                this.FinishOrder();
     634        }
     635       
     636        if (this.MoveToTarget(this.garrisoningTarget))
     637            this.SetNextState("INDIVIDUAL.GARRISON.WALKING");
     638        else
     639        {
     640            // We do a range check before actually garrisoning
     641            this.StopMoving();
     642            this.SetNextState("INDIVIDUAL.GARRISON.GARRISONED");
     643        }
     644    },
     645
    623646    "Order.Cheering": function(msg) {
    624647        this.SetNextState("INDIVIDUAL.CHEERING");
    625648    },
     
    22702293                    this.StopTimer();
    22712294                }
    22722295            },
     2296           
     2297            // Walking to a good place to garrison, used by Town Bell
     2298            "WALKING": {
     2299                "enter": function() {
     2300                    this.SelectAnimation("move");
     2301                },
    22732302
     2303                "MoveCompleted": function(msg) {
     2304                    // check that we can garrison in the building we're supposed to garrison in
     2305                    var cmpGarrisonHolder = Engine.QueryInterface(this.garrisoningTarget, IID_GarrisonHolder);
     2306                    if (!cmpGarrisonHolder || cmpGarrisonHolder.GetCapacity() <= cmpGarrisonHolder.GetEntities().length)
     2307                    {
     2308                        // Try to find another nearby building
     2309                        var nearby = this.FindNearbyGarrisonHolder();
     2310                        if (nearby)
     2311                        {
     2312                            this.garrisoningTarget = nearby;
     2313                            if (this.MoveToTarget(this.garrisoningTarget))
     2314                                this.SetNextState("WALKING");
     2315                        }
     2316                        else
     2317                            this.FinishOrder();
     2318                    }
     2319                    else
     2320                        this.SetNextState("GARRISONED");
     2321                },
     2322               
     2323                "leave": function() {
     2324                    this.StopTimer();
     2325                },
     2326            },
     2327
    22742328            "GARRISONED": {
    22752329                "enter": function() {
    2276                     var target = this.order.data.target;
     2330                    // Target is not handled the same way with TownBell and direct garrisoning
     2331                    if(this.order.data.target)
     2332                        var target = this.order.data.target;
     2333                    else
     2334                        var target = this.garrisoningTarget;
     2335                       
    22772336                    var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder);
    22782337
    22792338                    // Check that we can garrison here
     
    25282587   
    25292588    // To go back to work later
    25302589    this.lastWorkOrder = undefined;
     2590   
     2591    // Town Bell behaviour
     2592    this.townBellStriker = undefined;
     2593    this.garrisoningTarget = undefined;
    25312594
    25322595    // For preventing increased action rate due to Stop orders or target death.
    25332596    this.lastAttacked = undefined;
     
    28302893        var template = cmpTemplateManager.GetCurrentTemplateName(this.entity);
    28312894        error("FinishOrder called for entity " + this.entity + " (" + template + ") when order queue is empty\n" + stack);
    28322895    }
     2896   
     2897    // Forget all information about Town Bells (typically when finishing the TownBell order)
     2898    this.townBellStriker = undefined;
     2899    this.garrisoningTarget = undefined;
    28332900
    28342901    // Remove the order from the queue, then forget it if it was a work to avoid trying to go back to it later.
    28352902    var finishedOrder = this.orderQueue.shift();
     
    30083075    this.lastWorkOrder = order;
    30093076};
    30103077
     3078UnitAI.prototype.GetTownBellStriker = function()
     3079{
     3080    return this.townBellStriker;
     3081};
     3082
    30113083UnitAI.prototype.TimerHandler = function(data, lateness)
    30123084{
    30133085    // Reset the timer
     
    32523324};
    32533325
    32543326/**
     3327 * Returns the entity ID of the nearest building in which the unit can garrison,
     3328 * or undefined if none can be found close enough.
     3329 */
     3330UnitAI.prototype.FindNearbyGarrisonHolder = function()
     3331{
     3332    var range = 64; // TODO: what's a sensible number?
     3333
     3334    // Find buildings owned by this unit's player
     3335    var players = [];
     3336    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     3337    if (cmpOwnership)
     3338        players.push(cmpOwnership.GetOwner());
     3339
     3340    var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
     3341    var nearby = rangeMan.ExecuteQuery(this.entity, 0, range, players, IID_GarrisonHolder);
     3342    for each (var ent in nearby)
     3343    {
     3344        var cmpGarrisonHolder = Engine.QueryInterface(ent, IID_GarrisonHolder);
     3345        if (cmpGarrisonHolder.AllowedToGarrison(this.entity) && cmpGarrisonHolder.GetCapacity() > cmpGarrisonHolder.GetEntities().length)
     3346            return ent;
     3347    }
     3348
     3349    return undefined;
     3350};
     3351
     3352/**
    32553353 * Play a sound appropriate to the current entity.
    32563354 */
    32573355UnitAI.prototype.PlaySound = function(name)
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    400400                notifyBackToWorkFailure(player, worker)
    401401        }
    402402        break;
     403    case "ring-town-bell-yellow":
     404        var entities = FilterEntityList(cmd.strikers, player, controlAllUnits);
     405        for each (var striker in entities)
     406        {
     407            var cmpTownBellStriker = Engine.QueryInterface(striker, IID_TownBellStriker);
     408            if (!cmpTownBellStriker || !cmpTownBellStriker.RingYellowAlert())
     409                notifyBellFailure(player)
     410        }
     411        break;
     412   
     413    case "ring-town-bell-red":
     414        var entities = FilterEntityList(cmd.strikers, player, controlAllUnits);
     415        for each (var striker in entities)
     416        {
     417            var cmpTownBellStriker = Engine.QueryInterface(striker, IID_TownBellStriker);
     418            if (!cmpTownBellStriker || !cmpTownBellStriker.RingRedAlert())
     419                notifyBellFailure(player)
     420        }
     421        break;
     422   
     423    case "ring-town-bell-end":
     424        var entities = FilterEntityList(cmd.strikers, player, controlAllUnits);
     425        for each (var striker in entities)
     426        {
     427            var cmpTownBellStriker = Engine.QueryInterface(striker, IID_TownBellStriker);
     428            if (!cmpTownBellStriker || !cmpTownBellStriker.RingEndOfAlert())
     429                notifyBellFailure(player)
     430        }
     431        break;
    403432
    404433    case "formation":
    405434        GetFormationUnitAIs(entities, player, cmd.name).forEach(function(cmpUnitAI) {
     
    539568}
    540569
    541570/**
     571 * Sends a GUI notification about Town Bells that failed to be struck
     572 */
     573function notifyBellFailure(player)
     574{
     575    var cmpPlayer = QueryPlayerIDInterface(player, IID_Player);
     576    var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Unable to strike the Town Bell" };
     577    var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
     578    cmpGUIInterface.PushNotification(notification);
     579}
     580
     581/**
    542582 * Get some information about the formations used by entities.
    543583 * The entities must have a UnitAI component.
    544584 */
  • binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml

     
    9999    <Radius>140</Radius>
    100100    <Weight>65536</Weight>
    101101  </TerritoryInfluence>
     102  <TownBellStriker>
     103    <Range>140</Range>
     104  </TownBellStriker>
    102105  <Vision>
    103106    <Range>90</Range>
    104107  </Vision>