Ticket #1907: corral-v3.2.diff

File corral-v3.2.diff, 20.7 KB (added by mimo, 11 years ago)

with the CRTL key to corral an animal

  • binaries/data/mods/public/gui/session/selection_details.js

     
    166166        getGUIObjectByName("resourceCarryingText").caption = entState.resourceSupply.gatherers.length + " / " + entState.resourceSupply.maxGatherers + "    ";
    167167        getGUIObjectByName("resourceCarryingIcon").tooltip = "Current/max gatherers";
    168168    }
     169    // And for number of corraled animals
     170    else if (entState.corral)
     171    {
     172        getGUIObjectByName("resourceCarryingIcon").hidden = false;
     173        getGUIObjectByName("resourceCarryingText").hidden = false;
     174        getGUIObjectByName("resourceCarryingIcon").sprite = "stretched:session/portraits/structures/corral.png";
     175        getGUIObjectByName("resourceCarryingText").caption = entState.corral.entities.length + " / " + entState.corral.capacity + "    ";
     176        getGUIObjectByName("resourceCarryingIcon").tooltip = "Current/max corraled animals";
     177    }
    169178    else
    170179    {
    171180        getGUIObjectByName("resourceCarryingIcon").hidden = true;
  • binaries/data/mods/public/gui/session/input.js

     
    248248            if (targetState.garrisonHolder.entities.length >= targetState.garrisonHolder.capacity)
    249249                tooltip = "[color=\"orange\"]" + tooltip + "[/color]";
    250250        }
     251        else if (targetState.corral)
     252        {
     253            data.command = "corral";
     254            data.target = target;
     255            cursor = "action-gather-milk";
     256            tooltip = "Current corraled: " + targetState.corral.entities.length
     257                + "/" + targetState.corral.capacity;
     258            if (targetState.corral.entities.length >= targetState.corral.capacity)
     259                tooltip = "[color=\"orange\"]" + tooltip + "[/color]";
     260        }
    251261        else if (targetState.resourceSupply)
    252262        {
    253263            var resourceType = targetState.resourceSupply.type;
     
    349359                }
    350360            }
    351361            break;
     362        case "corral":
     363            if (hasClass(entState, "Unit") && targetState.corral)
     364            {
     365                var tooltip = "Current corraled: " + targetState.corral.entities.length
     366                    + "/" + targetState.corral.capacity;
     367                if (targetState.corral.entities.length >= targetState.corral.capacity)
     368                    tooltip = "[color=\"orange\"]" + tooltip + "[/color]";
     369                return {"possible": Engine.GuiInterfaceCall("CanBeCorraled", {"entity": entState.id, "corral": target}), "tooltip": tooltip};
     370            }
     371            break;
    352372        case "setup-trade-route":
    353373            // If ground or sea trade possible
    354374            if (!targetState.foundation && ((entState.trader && hasClass(entState, "Organic") && (playerOwned || allyOwned) && hasClass(targetState, "Market")) ||
     
    515535    {
    516536        return {"type": "garrison", "cursor": "action-garrison", "tooltip": actionInfo.tooltip, "target": target};
    517537    }
     538    else if (Engine.HotkeyIsPressed("session.corral") && (actionInfo = getActionInfo("corral", target)).possible)
     539    {
     540        return {"type": "corral", "cursor": "action-gather-milk", "tooltip": actionInfo.tooltip, "target": target};
     541    }
    518542    else if (Engine.HotkeyIsPressed("session.attackmove") && getActionInfo("attack-move", target).possible)
    519543    {
    520544            return {"type": "attack-move", "cursor": "action-attack-move"};
     
    13971421        Engine.GuiInterfaceCall("PlaySound", { "name": "order_garrison", "entity": selection[0] });
    13981422        return true;
    13991423
     1424    case "corral":
     1425        Engine.PostNetworkCommand({"type": "corral", "entities": selection, "target": action.target, "queued": queued});
     1426        Engine.GuiInterfaceCall("PlaySound", { "name": "order_corral", "entity": selection[0] });
     1427        return true;
     1428
    14001429    case "set-rallypoint":
    14011430        var pos = undefined;
    14021431        // if there is a position set in the action then use this so that when setting a
  • binaries/data/mods/public/gui/session/session.xml

     
    997997                <object size="90 -2 126 34" name="attackAndArmorStats" type="image" sprite="stretched:session/icons/stances/defensive.png" tooltip="Attack and Armor" tooltip_style="sessionToolTip"/>
    998998
    999999                <!-- Resource carrying icon/counter -->
    1000                 <!-- Used also for number of gatherers/builders -->
     1000                <!-- Used also for number of gatherers/builders/corraled -->
    10011001                <object size="100%-98 -2 100%-28 34" type="text" name="resourceCarryingText" style="CarryingTextRight"/>
    10021002                <object size="100%-36 -2 100% 34" type="image" name="resourceCarryingIcon" tooltip_style="sessionToolTip"/>
    10031003            </object>
  • binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml

     
    1010    <Square width="12.0" depth="22.0"/>
    1111    <Height>5.0</Height>
    1212  </Footprint>
    13   <GarrisonHolder>
    14     <Max>10</Max>
    15     <EjectHealth>0.1</EjectHealth>
    16     <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
    17     <List datatype="tokens">Animal</List>
    18     <BuffHeal>1</BuffHeal>
    19     <LoadingRange>2</LoadingRange>
    20   </GarrisonHolder>
     13  <Corral>
     14    <MaxCapacity>10</MaxCapacity>
     15    <Range>6</Range>
     16  </Corral>
    2117  <Health>
    2218    <Max>500</Max>
    2319    <SpawnEntityOnDeath>rubble/rubble_2x4</SpawnEntityOnDeath>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml

     
    1212    <Classes datatype="tokens">Domestic</Classes>
    1313    <Icon>gaia/fauna_sheep.png</Icon>
    1414  </Identity>
     15  <UnitAI>
     16    <CorralType>food</CorralType>
     17    <CorralRate>0.4</CorralRate>
     18  </UnitAI>
    1519  <Position>
    1620    <Anchor>pitch</Anchor>
    1721  </Position>
  • binaries/data/mods/public/simulation/templates/gaia/fauna_pig.xml

     
    55    <SpecificName>Pig</SpecificName>
    66    <Icon>gaia/fauna_pig.png</Icon>
    77  </Identity>
     8  <UnitAI>
     9    <CorralType>food</CorralType>
     10    <CorralRate>0.4</CorralRate>
     11  </UnitAI>
    812  <Position>
    913    <Anchor>pitch</Anchor>
    1014  </Position>
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    319319        }
    320320        break;
    321321
     322    case "corral":
     323        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
     324            cmpUnitAI.SetCorraled(cmd.target, cmd.queued);
     325        });
     326        break;
     327
    322328    case "stop":
    323329        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
    324330            cmpUnitAI.Stop(cmd.queued);
  • binaries/data/mods/public/simulation/helpers/RallyPointCommands.js

     
    6060                "queued": true
    6161            });
    6262            break;
     63        case "corral":
     64            ret.push( {
     65                "type": "corral",
     66                "entities": spawnedEnts,
     67                "target": data[i].target,
     68                "queued": true
     69            });
     70            break;
    6371        case "trade":
    6472            ret.push( {
    6573                "type": "setup-trade-route",
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    291291    }
    292292
    293293    var cmpResourceSupply = Engine.QueryInterface(ent, IID_ResourceSupply);
    294     if (cmpResourceSupply)
     294    if (cmpResourceSupply)
     295    {
     296        ret.resourceSupply = {
     297            "isInfinite": cmpResourceSupply.IsInfinite(),
     298            "max": cmpResourceSupply.GetMaxAmount(),
     299            "amount": cmpResourceSupply.GetCurrentAmount(),
     300            "type": cmpResourceSupply.GetType(),
     301            "killBeforeGather": cmpResourceSupply.GetKillBeforeGather(),
     302            "maxGatherers": cmpResourceSupply.GetMaxGatherers(),
     303            "gatherers": cmpResourceSupply.GetGatherers()
     304        };
     305    }
     306
     307    var cmpCorral = Engine.QueryInterface(ent, IID_Corral);
     308    if (cmpCorral)
    295309    {
    296         ret.resourceSupply = {
    297             "isInfinite": cmpResourceSupply.IsInfinite(),
    298             "max": cmpResourceSupply.GetMaxAmount(),
    299             "amount": cmpResourceSupply.GetCurrentAmount(),
    300             "type": cmpResourceSupply.GetType(),
    301             "killBeforeGather": cmpResourceSupply.GetKillBeforeGather(),
    302             "maxGatherers": cmpResourceSupply.GetMaxGatherers(),
    303             "gatherers": cmpResourceSupply.GetGatherers()
    304         };
    305     }
     310        ret.corral = {
     311            "entities": cmpCorral.GetEntities(),
     312            "capacity": cmpCorral.GetCapacity()
     313        };
     314    }
    306315
    307316    var cmpResourceGatherer = Engine.QueryInterface(ent, IID_ResourceGatherer);
    308317    if (cmpResourceGatherer)
     
    17161725    return cmpAttack.CanAttack(data.target);
    17171726};
    17181727
     1728GuiInterface.prototype.CanBeCorraled = function(player, data)
     1729{
     1730    var cmpCorral = Engine.QueryInterface(data.corral, IID_Corral);
     1731    if (!cmpCorral)
     1732        return false;
     1733
     1734    return cmpCorral.CanBeCorraled(data.entity);
     1735};
     1736
    17191737/*
    17201738 * Returns batch build time.
    17211739 */
     
    18011819    "GetTradingRouteGain": 1,
    18021820    "GetTradingDetails": 1,
    18031821    "CanAttack": 1,
     1822    "CanBeCorraled": 1,
    18041823    "GetBatchTime": 1,
    18051824
    18061825    "SetPathfinderDebugOverlay": 1,
  • binaries/data/mods/public/simulation/components/interfaces/Corral.js

     
     1Engine.RegisterInterface("Corral");
     2
     3// Message of the form { },
     4// sent to the current entity whenever the corraled units change.
     5Engine.RegisterMessageType("CorraledUnitsChanged");
  • binaries/data/mods/public/simulation/components/Corral.js

     
     1function Corral() {}
     2
     3Corral.prototype.Schema =
     4    "<element name='MaxCapacity' a:help='Maximum number of corraled units'>" +
     5        "<ref name='nonNegativeDecimal'/>" +
     6    "</element>" +
     7    "<element name='Range' a:help='Range distance of corraled units'>" +
     8        "<ref name='nonNegativeDecimal'/>" +
     9    "</element>";
     10
     11Corral.prototype.Init = function()
     12{
     13    this.entities = [];
     14    this.increment = 1;
     15    this.timer = undefined;
     16};
     17
     18Corral.prototype.GetCapacity = function()
     19{
     20    return +this.template.MaxCapacity;
     21};
     22
     23Corral.prototype.GetEntities = function()
     24{
     25    return this.entities;
     26};
     27
     28Corral.prototype.GetRange = function()
     29{
     30    return +this.template.Range;
     31};
     32
     33/**
     34 * Returns true if the entity ent can be corraled inside,
     35 */
     36Corral.prototype.CanBeCorraled = function(ent)
     37{
     38    var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
     39    if (!cmpUnitAI)
     40        return false;
     41    // Formation controllers should always respond to commands
     42    if (cmpUnitAI.IsFormationController())
     43        return true;
     44
     45    // The entity must have a corral type not null
     46    var entType = cmpUnitAI.GetCorralType();
     47    if (entType == null)
     48        return false;
     49    // And if there is already a corraled unit, it must have the same type
     50    var type = this.GetType();
     51    if (type != null && type != entType)
     52        return false;
     53    return true;
     54};
     55
     56Corral.prototype.AddCorraled = function(ent)
     57{
     58    if (this.entities.indexOf(ent) != -1 || this.entities.length >= this.GetCapacity())
     59        return false;
     60    this.entities.push(ent);
     61    Engine.PostMessage(this.entity, MT_CorraledUnitsChanged, {});
     62    return true;
     63};
     64
     65Corral.prototype.RemoveCorraled = function(ent)
     66{
     67    if (this.entities.indexOf(ent) == -1)
     68        return;
     69    this.entities.splice(this.entities.indexOf(ent), 1);
     70    Engine.PostMessage(this.entity, MT_CorraledUnitsChanged, {});
     71};
     72
     73Corral.prototype.GetRate = function()
     74{
     75    var rate = 0;
     76    for each (var ent in this.entities)
     77    {
     78        var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
     79        rate += cmpUnitAI.GetCorralRate();
     80    }
     81    rate = ApplyTechModificationsToEntity("Corral/Rate", rate, this.entity);
     82    return rate;
     83}
     84
     85Corral.prototype.GetType = function()
     86{
     87    var type = null;
     88    if (this.entities.length > 0)
     89    {
     90        var cmpUnitAI = Engine.QueryInterface(this.entities[0], IID_UnitAI);
     91        type= cmpUnitAI.GetCorralType();
     92    }
     93    return type;
     94}
     95
     96/**
     97 * Called every second. Produce food (in corrals)
     98 */
     99Corral.prototype.Timeout = function(data)
     100{
     101    var type = this.GetType();
     102    var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     103    if (type != null)
     104    {
     105        var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
     106        cmpPlayer.AddResource(type, this.increment);
     107        var cmpStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
     108        if (cmpStatisticsTracker)
     109            cmpStatisticsTracker.IncreaseResourceGatheredCounter(type, this.increment);
     110
     111        var rate = this.GetRate();
     112        this.increment = this.entities.length;
     113        this.timer = cmpTimer.SetTimeout(this.entity, IID_Corral, "Timeout", this.increment*1000/rate, {});
     114    }
     115    else
     116    {
     117        cmpTimer.CancelTimer(this.timer);
     118        this.timer = undefined;
     119    }
     120};
     121
     122
     123Corral.prototype.OnCorraledUnitsChanged = function(msg)
     124{
     125    // first clear the cache for technology modifications (the total rate has changed)
     126    var cmpTechMan = QueryOwnerInterface(this.entity, IID_TechnologyManager);
     127    if (cmpTechMan)
     128        cmpTechMan.clearModificationCache(this.entity);
     129
     130    if (this.entities.length > 0 && !this.timer)
     131    {
     132        var rate = this.GetRate();
     133        this.increment = this.entities.length;
     134        var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     135        this.timer = cmpTimer.SetTimeout(this.entity, IID_Corral, "Timeout", this.increment*1000/rate, {});
     136    }
     137    else if (this.entities.length == 0 && this.timer)
     138    {
     139        var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     140        cmpTimer.CancelTimer(this.timer);
     141        this.timer = undefined;
     142    }
     143};
     144
     145Corral.prototype.OnDestroy = function()
     146{
     147    if (this.timer)
     148    {
     149        var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     150        cmpTimer.CancelTimer(this.timer);
     151    }
     152
     153    for (var i = this.entities.length; i > 0; --i)
     154    {
     155        var cmpUnitAI = Engine.QueryInterface(this.entities[i-1], IID_UnitAI);
     156        if (cmpUnitAI)
     157            cmpUnitAI.UnsetCorraled();
     158    }
     159};
     160
     161
     162Engine.RegisterComponentType(IID_Corral, "Corral", Corral);
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    4646                "<ref name='positiveDecimal'/>" +
    4747            "</element>"+
    4848        "</interleave>" +
     49    "</optional>" +
     50    "<optional>" +
     51        "<interleave>" +
     52            "<element name='CorralType' a:help='Production type when corraled'>" +
     53                "<choice>" +
     54                    "<value>food</value>" +
     55                    "<value>metal</value>" +
     56                "</choice>" +
     57            "</element>" +
     58            "<element name='CorralRate' a:help='Production rate per sec when corraled'>" +
     59                "<ref name='positiveDecimal'/>" +
     60            "</element>" +
     61        "</interleave>" +
    4962    "</optional>";
    5063
    5164// Unit stances.
     
    620633        }
    621634    },
    622635
     636    "Order.Corral": function(msg) {
     637        var cmpCorral = Engine.QueryInterface(msg.data.target, IID_Corral);
     638        if (!cmpCorral)
     639        {
     640            this.FinishOrder();
     641            return;
     642        }
     643
     644        var range = cmpCorral.GetRange();
     645        if (this.MoveToTargetRangeExplicit(this.order.data.target, 0, range))
     646        {
     647            this.SetNextState("ANIMAL.CORRAL.APPROACHING");
     648        }
     649        else
     650        {
     651            this.StopMoving();
     652            this.SetNextState("ANIMAL.CORRAL.CORRALED");
     653        }
     654    },
     655
    623656    "Order.Cheering": function(msg) {
    624657        this.SetNextState("INDIVIDUAL.CHEERING");
    625658    },
     
    905938            this.SetNextStateAlwaysEntering("MEMBER");
    906939        },
    907940
     941        "Order.Corral": function(msg) {
     942            var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     943            cmpFormation.SetRearrange(false);
     944            cmpFormation.CallMemberFunction("SetCorraled", [msg.data.target, false]);
     945
     946            this.SetNextStateAlwaysEntering("MEMBER");
     947        },
     948
    908949        "IDLE": {
    909950        },
    910951
     
    23822423            this.SetNextState("FLEEING");
    23832424        },
    23842425
     2426
     2427        "Order.Corral": function(msg) {
     2428            var cmpCorral = Engine.QueryInterface(msg.data.target, IID_Corral);
     2429            if (!cmpCorral)
     2430            {
     2431                this.FinishOrder();
     2432                return;
     2433            }
     2434
     2435            var range = cmpCorral.GetRange();
     2436            if (this.MoveToTargetRangeExplicit(this.order.data.target, 0, range))
     2437            {
     2438                this.SetNextState("ANIMAL.CORRAL.APPROACHING");
     2439            }
     2440            else
     2441            {
     2442                this.StopMoving();
     2443                this.SetNextState("ANIMAL.CORRAL.CORRALED");
     2444            }
     2445        },
     2446
    23852447        "IDLE": {
    23862448            // (We need an IDLE state so that FinishOrder works)
    23872449
     
    23922454            },
    23932455        },
    23942456
     2457        'CORRAL': {
     2458            'APPROACHING': {
     2459                "MoveCompleted": function() {
     2460                    var cmpCorral = Engine.QueryInterface(this.order.data.target, IID_Corral);
     2461                    if (cmpCorral)
     2462                    {
     2463                        var range = cmpCorral.GetRange();
     2464                        var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion);
     2465                        if (cmpUnitMotion.IsInTargetRange(this.order.data.target, 0, range))
     2466                        {
     2467                            this.SetNextState("ANIMAL.CORRAL.CORRALED");
     2468                            return;
     2469                        }                       
     2470                    }
     2471                    this.FinishOrder();
     2472                },
     2473            },
     2474
     2475            'CORRALED': {
     2476                "enter": function() {
     2477                    this.corral = this.order.data.target;
     2478                    var cmpCorral = Engine.QueryInterface(this.corral, IID_Corral);
     2479                    if (!cmpCorral || !cmpCorral.AddCorraled(this.entity))
     2480                    {
     2481                        this.SetNextState("ROAMING");
     2482                        return true;
     2483                    }
     2484                    this.SelectAnimation("feeding");
     2485                    return false;
     2486                },
     2487
     2488                "Order.UnsetCorraled": function() {
     2489                    this.FinishOrder();
     2490                },
     2491
     2492                "leave": function() {
     2493                    if (this.corral)
     2494                    {
     2495                        var cmpCorral = Engine.QueryInterface(this.corral, IID_Corral);
     2496                        if (cmpCorral)
     2497                            cmpCorral.RemoveCorraled(this.entity);
     2498                        delete this.corral;
     2499                    }
     2500                },
     2501            },
     2502        },
     2503
    23952504        "ROAMING": {
    23962505            "enter": function() {
    23972506                // Walk in a random direction
     
    37813890        case "ReturnResource":
    37823891        case "Repair":
    37833892        case "Garrison":
     3893        case "Corral":
    37843894            // Find the target unit's position
    37853895            var cmpTargetPosition = Engine.QueryInterface(order.data.target, IID_Position);
    37863896            if (!cmpTargetPosition || !cmpTargetPosition.IsInWorld())
     
    45214631
    45224632//// Animal specific functions ////
    45234633
     4634/**
     4635 * Adds setcorraled order to the queue, forced by the player.
     4636 */
     4637UnitAI.prototype.SetCorraled = function(target, queued)
     4638{
     4639    var cmpCorral = Engine.QueryInterface(target, IID_Corral);
     4640    if (!cmpCorral || !cmpCorral.CanBeCorraled(this.entity))
     4641    {
     4642        this.WalkToTarget(target, queued);
     4643        return;
     4644    }
     4645    this.AddOrder("Corral", { "target": target, "force": true }, queued);
     4646};
     4647
     4648/**
     4649 * Adds unsetcorraled order to the queue.
     4650 */
     4651UnitAI.prototype.UnsetCorraled = function()
     4652{
     4653    if (this.corral)
     4654        this.AddOrder("UnsetCorraled", null, false);
     4655};
     4656
     4657UnitAI.prototype.GetCorralRate = function()
     4658{
     4659    return +(this.template.CorralRate || 0);
     4660};
     4661
     4662UnitAI.prototype.GetCorralType = function()
     4663{
     4664    return (this.template.CorralType || null);
     4665};
     4666
    45244667UnitAI.prototype.MoveRandomly = function(distance)
    45254668{
    45264669    // We want to walk in a random direction, but avoid getting stuck
  • binaries/data/config/default.cfg

     
    270270hotkey.session.attack = "Ctrl+Alt"          ; Modifier to force attack instead of another action
    271271hotkey.session.garrison = Ctrl              ; Modifier to garrison when clicking on building
    272272hotkey.session.attackmove = Ctrl            ; Modifier to attackmove when clicking on a point
     273hotkey.session.corral = Ctrl                ; Modifier to corral an animal
    273274hotkey.session.queue = Shift                ; Modifier to queue unit orders instead of replacing
    274275hotkey.session.batchtrain = Shift           ; Modifier to train units in batches
    275276hotkey.session.massbarter = Shift           ; Modifier to barter bunch of resources