Ticket #2266: Guard.diff

File Guard.diff, 22.8 KB (added by dajayalol, 11 years ago)

i wrecked some function of garrison and lobby in this patch

  • binaries/data/mods/public/art/textures/cursors/action-guard-disabled.png

    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
  • binaries/data/mods/public/art/textures/cursors/action-guard-disabled.txt

    Property changes on: binaries/data/mods/public/art/textures/cursors/action-guard-disabled.png
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +application/octet-stream
    \ No newline at end of property
     
     11 1
  • binaries/data/mods/public/art/textures/ui/session/icons/guard.png

    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    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/guard.png
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +application/octet-stream
    \ No newline at end of property
     
    1515const ACTION_NONE = 0;
    1616const ACTION_GARRISON = 1;
    1717const ACTION_REPAIR = 2;
     18const ACTION_GUARD = 3;
    1819var preSelectedAction = ACTION_NONE;
    1920
    2021const INPUT_NORMAL = 0;
     
    246247            if (targetState.garrisonHolder.garrisonedEntitiesCount >= targetState.garrisonHolder.capacity)
    247248                tooltip = "[color=\"orange\"]" + tooltip + "[/color]";
    248249        }
     250        if (targetState.guard && (playerOwned || mutualAllyOwned))
     251        {
     252            data.command = "guard";
     253            data.target = target;
     254            cursor = "action-guard";
     255            tooltip = "Current guard: " + targetState.guard.entities.length
     256                + "/" + targetState.guard.capacity;
     257            if (targetState.guard.entities.length >= targetState.guard.capacity)
     258                tooltip = "[color=\"red\"]" + tooltip + "[/color]";
     259        }
    249260        else if (targetState.resourceSupply)
    250261        {
    251262            var resourceType = targetState.resourceSupply.type;
     
    303314                if (target === selection[i])
    304315                    return {"possible": false};
    305316        }
     317        // Don't allow the rally point to be set on any of the currently selected entities
     318        for (var i = 0; i < selection.length; i++)
     319            if (target === selection[i])
     320                return {"possible": false};
    306321
    307322        return {"possible": true, "data": data, "position": targetState.position, "cursor": cursor, "tooltip": tooltip};
    308323    }
     
    347362                }
    348363            }
    349364            break;
     365        case "guard":
     366            if (hasClass(entState, "Unit") && targetState.guard && (playerOwned || mutualAllyOwned))
     367            {
     368                var tooltip = "Current guarding: " + targetState.guard.entities.length
     369                    + "/" + targetState.guard.capacity;
     370                if (targetState.guard.entities.length >= targetState.guard.capacity)
     371                    tooltip = "[color=\"orange\"]" + tooltip + "[/color]";
     372                var allowedClasses = targetState.guard.allowedClasses;
     373                        return {"possible": true, "tooltip": tooltip};
     374            }
     375            break;
    350376        case "setup-trade-route":
    351377            // If ground or sea trade possible
    352378            if (!targetState.foundation && ((entState.trader && hasClass(entState, "Organic") && (playerOwned || allyOwned) && hasClass(targetState, "Market")) ||
     
    502528            else
    503529                return {"type": "none", "cursor": "action-repair-disabled", "target": undefined};
    504530            break;
     531        case ACTION_GUARD:
     532            if ((actionInfo = getActionInfo("guard", target)).possible)
     533                return {"type": "guard", "cursor": "action-guard", "tooltip": actionInfo.tooltip, "target": target};
     534            else
     535                return {"type": "none", "cursor": "action-guard-disabled", "target": undefined};
     536            break;
    505537        }
    506538    }
    507539    else if (Engine.HotkeyIsPressed("session.attack") && getActionInfo("attack", target).possible)
     
    516548    {
    517549            return {"type": "attack-move", "cursor": "action-attack-move"};
    518550    }
     551        else if (haveUnitAI && Engine.HotkeyIsPressed("session.guard") && getActionInfo("guard", target).possible)
     552    {
     553            return {"type": "guard", "cursor": "action-guard"};
     554    }
    519555    else
    520556    {
    521557        if ((actionInfo = getActionInfo("setup-trade-route", target)).possible)
     
    13731409        Engine.PostNetworkCommand({"type": "repair", "entities": selection, "target": action.target, "autocontinue": true, "queued": queued});
    13741410        Engine.GuiInterfaceCall("PlaySound", { "name": "order_repair", "entity": selection[0] });
    13751411        return true;
    1376 
     1412    case "guard":
     1413        Engine.PostNetworkCommand({"type": "guard", "entities": selection, "target": action.target, "queued": queued});
     1414        Engine.GuiInterfaceCall("PlaySound", { "name": "order_guard", "entity": selection[0] });
     1415        return true;
    13771416    case "gather":
    13781417        Engine.PostNetworkCommand({"type": "gather", "entities": selection, "target": action.target, "queued": queued});
    13791418        Engine.GuiInterfaceCall("PlaySound", { "name": "order_gather", "entity": selection[0] });
     
    18161855                inputState = INPUT_PRESELECTEDACTION;
    18171856                preSelectedAction = ACTION_GARRISON;
    18181857                break;
     1858            case "guard":
     1859                inputState = INPUT_PRESELECTEDACTION;
     1860                preSelectedAction = ACTION_GUARD;
     1861                break;
    18191862            case "repair":
    18201863                inputState = INPUT_PRESELECTEDACTION;
    18211864                preSelectedAction = ACTION_REPAIR;
  • binaries/data/mods/public/gui/session/unit_commands.js

     
    22const SELECTION = "Selection";
    33const QUEUE = "Queue";
    44const GARRISON = "Garrison";
     5const GUARD = "Guard";
    56const FORMATION = "Formation";
    67const TRAINING = "Training";
    78const RESEARCH = "Research";
  • binaries/data/mods/public/gui/session/utility_functions.js

     
    274274            "tooltip": "Garrison",
    275275            "icon": "garrison.png"
    276276        });
     277        commands.push({
     278            "name": "guard",
     279            "tooltip": "Guard",
     280            "icon": "guard.png"
     281        });
    277282    }
    278283
    279284    if (entState.buildEntities)
  • binaries/data/mods/public/simulation/components/Guard.js

     
     1function Guard() {}
     2
     3Guard.prototype.Schema =
     4    "<a:component type='system'/><empty/>";
     5
     6Guard.prototype.Init = function()
     7{
     8    this.VIP={};
     9    // Guardian Units
     10    this.entities = [];
     11    this.timer = undefined;
     12    this.allowGuarding = true;
     13        this.capacity = 20;
     14};
     15
     16Guard.prototype.GetEntities = function()
     17{
     18    return this.entities;
     19};
     20Guard.prototype.GetCapacity = function()
     21{
     22    return this.capacity;
     23};
     24Guard.prototype.GetVIP = function()
     25{
     26    return this.VIP;
     27};
     28
     29Guard.prototype.AllowGuarding = function(allow, callerID)
     30{
     31    this.allowGuarding[callerID] = allow;
     32};
     33Guard.prototype.AddGuards = function(entity)
     34{
     35    if (this.entities.length >= this.GetCapacity())
     36        return false;
     37
     38    var cmpPosition = Engine.QueryInterface(entity, IID_Position);
     39    if (!cmpPosition)
     40        return false;
     41        //code
     42   
     43    this.entities.push(entity);
     44    Engine.PostMessage(this.entity, MT_GuardingUnitsChanged, {});
     45    return true;
     46};
     47Guard.prototype.EntityLeave = function(entity)
     48{
     49        var entityIndex = this.entities.indexOf(entity)
     50        if (entityIndex != -1)
     51        {
     52        this.entities.splice(entityIndex, 1);
     53        Engine.PostMessage(this.entity, MT_GuardingUnitsChanged, {});
     54        }
     55       
     56};
     57Guard.prototype.CanGuard = function(target)
     58{
     59    const cmpIdentity = Engine.QueryInterface(target, IID_Identity);
     60    if (!cmpIdentity)
     61        return undefined;
     62
     63    const targetClasses = cmpIdentity.GetClassesList();
     64
     65            return true;
     66    return false;
     67};
     68Guard.prototype.CheckGuardRange = function(target)
     69{
     70    const cmpIdentity = Engine.QueryInterface(target, IID_Identity);
     71    if (!cmpIdentity)
     72        return undefined;
     73
     74    const targetClasses = cmpIdentity.GetClassesList();
     75
     76            return true;
     77    return false;
     78};
     79Guard.prototype.OnOwnershipChanged = function(msg)
     80{
     81   
     82};
     83Guard.prototype.OnDestroy = function(msg)
     84{
     85   
     86};
     87/**
     88 * If a guarded entity is captured, or about to be killed (so its owner
     89 * changes to '-1'), remove it from the building so we only ever contain valid
     90 * entities
     91 */
     92Guard.prototype.OnGlobalOwnershipChanged = function(msg)
     93{
     94    // the ownership change may be on the VIP
     95    if (this.entity == msg.entity)
     96    {
     97        var entities = [];
     98        for each (var entity in this.entities)
     99        {
     100            if (msg.to == -1 || !IsOwnedByMutualAllyOfEntity(this.entity, entity))
     101                entities.push(entity);
     102        }
     103        this.EjectOrKill(entities);
     104        return;
     105    }
     106
     107    // or on some of its guarded units
     108    var entityIndex = this.entities.indexOf(msg.entity);
     109    if (entityIndex != -1)
     110    {
     111        // If the entity is dead, remove it directly instead of ejecting the corpse
     112        var cmpHealth = Engine.QueryInterface(msg.entity, IID_Health);
     113        if (cmpHealth && cmpHealth.GetHitpoints() == 0)
     114        {
     115            this.entities.splice(entityIndex, 1);
     116            Engine.PostMessage(this.entity, MT_GuardingUnitsChanged, {});
     117        }
     118        else if(!IsOwnedByMutualAllyOfEntity(this.entity, this.entities[entityIndex]))
     119            this.EjectOrKill([this.entities[entityIndex]]);
     120    }
     121};
     122
     123Guard.prototype.OnGlobalEntityRenamed = function(msg)
     124{
     125    var entityIndex = this.entities.indexOf(msg.entity);
     126    if (entityIndex != -1)
     127    {
     128        this.entities[entityIndex] = msg.newentity;
     129        Engine.PostMessage(this.entity, MT_GuardingUnitsChanged, {});
     130    }
     131};
     132Guard.prototype.EjectOrKill = function(entities)
     133{
     134
     135    // And destroy all remaining entities
     136    for each (var entity in entities)
     137    {
     138        var entityIndex = this.entities.indexOf(entity);
     139        if (entityIndex == -1)
     140            continue;
     141        var cmpHealth = Engine.QueryInterface(entity, IID_Health);
     142        if (cmpHealth)
     143       
     144        this.entities.splice(entityIndex, 1);
     145    }
     146
     147    Engine.PostMessage(this.entity, MT_GuardingUnitsChanged, {});
     148};
     149Guard.prototype.Unload = function(entity, forced)
     150{
     151    return this.PerformEject([entity], forced);
     152};
     153Guard.prototype.OnHealthChanged = function(msg)
     154{
     155};
     156Guard.prototype.HasEnoughHealth = function()
     157{
     158    var cmpHealth = Engine.QueryInterface(this.entity, IID_Health)
     159    var hitpoints = cmpHealth.GetHitpoints();
     160    var maxHitpoints = cmpHealth.GetMaxHitpoints();
     161    var ejectHitpoints = Math.floor((+this.template.EjectHealth) * maxHitpoints);
     162    return hitpoints > ejectHitpoints;
     163};
     164/**
     165 * Ejects units and orders them to move to the Rally Point.
     166 * Returns true if successful, false if not
     167 */
     168Guard.prototype.PerformEject = function(entities, forced)
     169{
     170    if (!this.allowGuarding() && !forced)
     171        return false;
     172
     173    var ejectedEntities = [];
     174    var success = true;
     175    for each (var entity in entities)
     176    {
     177        if (this.Eject(entity, forced))
     178        {
     179            var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     180            var cmpEntOwnership = Engine.QueryInterface(entity, IID_Ownership);
     181            if (cmpOwnership && cmpEntOwnership && cmpOwnership.GetOwner() == cmpEntOwnership.GetOwner())
     182                ejectedEntities.push(entity);
     183        }
     184        else
     185            success = false;
     186    }
     187
     188    return success;
     189};
     190
     191Engine.RegisterComponentType(IID_Guard, "Guard", Guard);
     192 No newline at end of file
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    308308    {
    309309        ret.resourceGatherRates = cmpResourceGatherer.GetGatherRates();
    310310        ret.resourceCarrying = cmpResourceGatherer.GetCarryingStatus();
     311    }
     312    var cmpGuard = Engine.QueryInterface(ent, IID_Guard);
     313    if (cmpGuard)
     314    {
     315        ret.guard = {
     316            "entities": cmpGuard.GetEntities(),
     317            "capacity": cmpGuard.GetCapacity(),
     318        };
    311319    }
    312 
    313320    var cmpResourceDropsite = Engine.QueryInterface(ent, IID_ResourceDropsite);
    314321    if (cmpResourceDropsite)
    315322    {
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    331331            this.FinishOrder();
    332332        }
    333333    },
    334 
     334    "Order.WalkToTargetRange": function(msg) {
     335            if (this.MoveToTargetRangeExplicit(this.order.data.target, this.order.data.min, this.order.data.max))
     336                this.SetNextState("WALKING");
     337            else
     338                this.FinishOrder();
     339        },
    335340    "Order.PickupUnit": function(msg) {
    336341        var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
    337342        if (!cmpGarrisonHolder || cmpGarrisonHolder.IsFull())
     
    659664            this.SetNextState("INDIVIDUAL.GARRISON.GARRISONED");
    660665        }
    661666    },
    662 
     667    "Order.Guard": function(msg) {
     668        // For packable units:
     669        // 1. If packed, we can move to the garrison target.
     670        // 2. If unpacked, we first need to pack, then follow case 1.
     671        this.SetNextState("INDIVIDUAL.GUARD.APPROACHING");
     672        if (this.CanPack())
     673        {
     674            // Case 2: pack
     675            this.PushOrderFront("Pack", { "force": true });
     676            return;
     677        }
     678    },
    663679    "Order.Autogarrison": function(msg) {
    664680        this.SetNextState("INDIVIDUAL.AUTOGARRISON");
    665681    },
     
    797813
    798814            this.SetNextState("GARRISON.GARRISONING");
    799815        },
     816        "Order.Guard": function(msg) {
     817            // TODO: on what should we base this range?
     818            // Check if we are already in range, otherwise walk there
     819            if (!this.CheckTargetRangeExplicit(msg.data.target, 0, 10))
     820            {
     821                if (!this.CheckTargetVisible(msg.data.target))
     822                {
     823                if (!this.TargetIsAlive(msg.data.target) || !this.CheckTargetVisible(msg.data.target))
     824                    // The target was destroyed
     825                    this.FinishOrder();
     826                }
     827                else
     828                {
     829                    // Out of range; move there in formation
     830                    this.PushOrderFront("WalkToTargetRange", { "target": msg.data.target, "min": 0, "max": 10 });
     831                    return;
     832                }
     833               
     834            // We don't want to rearrange the formation if the individual units are carrying
     835            // out a task and one of the members dies/leaves the formation.
     836            }
     837            var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
     838            // We don't want to rearrange the formation if the individual units are carrying
     839            // out a task and one of the members dies/leaves the formation.
     840            cmpFormation.SetRearrange(false);
     841            cmpFormation.CallMemberFunction("Guard", [msg.data.target, false]);
    800842
     843           
     844
     845            this.SetNextStateAlwaysEntering("MEMBER");
     846        },
     847
    801848        "Order.Gather": function(msg) {
    802849            if (this.MustKillGatherTarget(msg.data.target))
    803850            {
     
    10971144                cmpFormation.FindInPosition();
    10981145            }
    10991146        },
    1100 
    11011147        "MEMBER": {
    11021148            // Wait for individual members to finish
    11031149            "enter": function(msg) {
     
    20022048                },
    20032049            },
    20042050        },
     2051        "GUARD": {
     2052            "APPROACHING": {
     2053                "enter": function() {
     2054                    this.SelectAnimation("move");
     2055                },
     2056                "MoveCompleted": function() {
     2057                    this.SetNextState("GUARDING");
     2058                },
     2059               
     2060                "leave": function() {
     2061                    this.StopTimer();
     2062                }
     2063                    }
     2064            },
     2065        "GUARDING":{
     2066        "enter": function() {
     2067        var target = this.order.data.target;
     2068        var cmpGuard = Engine.QueryInterface(target, IID_Guard);
     2069        this.VIP=cmpGuard.GetVIP;
    20052070
     2071        // Check that we can guard here
     2072                if (cmpGuard.CanGuard(target))
     2073                {
     2074                    // Check that we're in range of the guarded target
     2075                    if (cmpGuard.CheckGuardRange(target))
     2076                    {
     2077                        // Check that garrisoning succeeds
     2078                        if (cmpGuard.AddGuards(this.entity))
     2079                        {
     2080                            this.isGuarding = true;
     2081                            this.VIP=target;
     2082                            return;}
     2083                    }   
     2084                }
     2085                },
     2086        "leave": function() {
     2087        this.StopTimer();
     2088        this.isGuarding = false;
     2089        var cmpGuard = Engine.QueryInterface(this.VIP, IID_Guard);
     2090        cmpGuard.EntityLeave(this.entity);
     2091        this.VIP=undefined;
     2092        return;
     2093                }
     2094    },
    20062095        "HEAL": {
    20072096            "Attacked": function(msg) {
    20082097                // If we stand ground we will rather die than flee
     
    27052794    this.order = undefined; // always == this.orderQueue[0]
    27062795    this.formationController = INVALID_ENTITY; // entity with IID_Formation that we belong to
    27072796    this.isGarrisoned = false;
     2797    this.isGuarding = false;
    27082798    this.isIdle = false;
    27092799    this.lastFormationName = "";
    27102800    this.finishedOrder = false; // used to find if all formation members finished the order
     
    27722862{
    27732863    return this.isGarrisoned;
    27742864};
    2775 
     2865UnitAI.prototype.IsGuarding = function()
     2866{
     2867    return this.IsGuarding;
     2868};
    27762869UnitAI.prototype.IsWalking = function()
    27772870{
    27782871    var state = this.GetCurrentState().split(".").pop();
     
    41824275        case "ReturnResource":
    41834276        case "Repair":
    41844277        case "Garrison":
     4278        case "Guard":
    41854279            // Find the target unit's position
    41864280            var cmpTargetPosition = Engine.QueryInterface(order.data.target, IID_Position);
    41874281            if (!cmpTargetPosition || !cmpTargetPosition.IsInWorld())
     
    42094303    // Return the total distance to the end of the order queue
    42104304    return distance;
    42114305};
    4212 
     4306UnitAI.prototype.Guard = function(target, queued)
     4307{
     4308    if (!this.CanGuard(target))
     4309    {
     4310        this.WalkToTarget(target, queued);
     4311        return;
     4312    }
     4313    this.WalkToTarget(target, queued);
     4314+   this.AddOrder("Guard", { "target": target, "force": true }, queued);
     4315};
    42134316UnitAI.prototype.AddOrder = function(type, data, queued)
    42144317{
    42154318    if (queued)
     
    49075010
    49085011    return true;
    49095012};
     5013UnitAI.prototype.CanGuard = function(target)
     5014{
     5015    // Formation controllers should always respond to commands
     5016    // (then the individual units can make up their own minds)
     5017    if (this.IsFormationController())
     5018        return true;
     5019 
     5020    var cmpGuard = Engine.QueryInterface(target, IID_Guard);
     5021    if (!cmpGuard)
     5022        return false;
    49105023
     5024    // Verify that the target is owned by this entity's player or a mutual ally of this player
     5025    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     5026    if (!cmpOwnership || !(IsOwnedByPlayer(cmpOwnership.GetOwner(), target) || IsOwnedByMutualAllyOfPlayer(cmpOwnership.GetOwner(), target)))
     5027        return false;
     5028
     5029    // Don't let animals garrison for now
     5030    // (If we want to support that, we'll need to change Order.Garrison so it
     5031    // doesn't move the animal into an INVIDIDUAL.* state)
     5032    if (this.IsAnimal())
     5033        return false;
     5034    return true;
     5035};
    49115036UnitAI.prototype.CanPack = function()
    49125037{
    49135038    var cmpPack = Engine.QueryInterface(this.entity, IID_Pack);
  • binaries/data/mods/public/simulation/components/interfaces/Guard.js

     
     1Engine.RegisterInterface("Guard");
     2
     3// Message of the form { } (use GetEntities if you want the current details),
     4// sent to the current entity whenever the garrisoned units change.
     5Engine.RegisterMessageType("GuardingUnitsChanged");
     6 No newline at end of file
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    156156            cmpUnitAI.GatherNearPosition(cmd.x, cmd.z, cmd.resourceType, cmd.resourceTemplate, cmd.queued);
    157157        });
    158158        break;
    159 
     159    case "guard":
     160        // Verify that the building can be controlled by the player or is mutualAlly
     161        if (CanControlUnitOrIsAlly(cmd.target, player, controlAllUnits))
     162        {
     163            GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
     164                cmpUnitAI.Guard(cmd.target, cmd.queued);
     165            });
     166            warn("Invalid command: guard is in alpha state "+player+" (or ally): "+uneval(cmd));
     167       
     168        }
     169        else if (g_DebugCommands)
     170        {
     171            warn("Invalid command: garrison target cannot be controlled by player "+player+" (or ally): "+uneval(cmd));
     172        }
     173        break;
    160174    case "returnresource":
    161175        // Check dropsite is owned by player
    162176        if (g_DebugCommands && !IsOwnedByPlayer(player, cmd.target))
  • binaries/data/mods/public/simulation/templates/template_unit.xml

     
    5353    </Formations>
    5454  </Identity>
    5555  <Looter/>
     56  <Guard>
     57  </Guard>
    5658  <Minimap>
    5759    <Type>unit</Type>
    5860  </Minimap>
  • binaries/system/Quickstart.bat

    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
     
    1 start pyrogenesis.exe -quickstart
     1start pyrogenesis.exe -quickstart
     2 No newline at end of file