Ticket #1719: AttackNotificationApr062013.patch

File AttackNotificationApr062013.patch, 18.2 KB (added by madmax, 11 years ago)

The patch file for adding attack notification to 0AD

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

     
    7878            "amounts": notification.amounts
    7979        });
    8080    }
     81    else if (notification.type == "attack")
     82    {
     83        if (notification.player == Engine.GetPlayerID())
     84        {
     85            Engine.GuiInterfaceCall("PlaySound", { "name":"attacked", "entity": notification.message.target });
     86        }
     87    }
    8188    else
    8289    {
    8390        // Only display notifications directed to this player
     
    356363
    357364        formatted = "[color=\"" + playerColor + "\"]" + username + "[/color] has sent you " + amounts + ".";
    358365        break;
     366    case "attack":
     367        if (msg.player != Engine.GetPlayerID())
     368            return;
     369
     370        formatted = "We're under attack!";
     371        break;
    359372    case "message":
    360373        // May have been hidden by the 'team' command.
    361374        if (msg.hide)
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    620620    return cmpBattleDetection.GetState();
    621621};
    622622
     623// Returns a list of ongoing attacks against the player.
     624GuiInterface.prototype.GetIncomingAttacks = function(player)
     625{
     626    var cmpAttackDetection = QueryPlayerIDInterface(player, IID_AttackDetection);
     627    return cmpAttackDetection.GetIncomingAttacks();
     628};
     629
    623630// Used to show a red square over GUI elements you can't yet afford.
    624631GuiInterface.prototype.GetNeededResources = function(player, amounts)
    625632{
     
    17201727    "CheckTechnologyRequirements": 1,
    17211728    "GetStartedResearch": 1,
    17221729    "GetBattleState": 1,
     1730    "GetIncomingAttacks": 1,
    17231731    "GetNeededResources": 1,
    17241732    "GetNextNotification": 1,
    17251733
  • binaries/data/mods/public/simulation/components/interfaces/AttackDetection.js

     
     1Engine.RegisterInterface("AttackDetection");
     2
     3// Message of the form { "target": 123, "x": 123, "z": 456, "time": 1 }.
     4// sent when an entity is attacked.
     5//Engine.RegisterMessageType("EntityAttacked");
     6
     7// Message of the form { "player": 1, "event": { "target": 123 , "position": { "x": 123, "z": 456 }, "time": 1, }.
     8// sent when a new attack is detected.
     9Engine.RegisterMessageType("AttackDetected");
  • binaries/data/mods/public/simulation/templates/special/player.xml

     
    1212  <Player/>
    1313  <StatisticsTracker/>
    1414  <TechnologyManager/>
     15  <AttackDetection/>
    1516  <BattleDetection>
    1617    <TimerInterval>200</TimerInterval>
    1718    <RecordLength>12</RecordLength>
  • binaries/data/mods/public/simulation/templates/template_structure.xml

     
    8585      <select>interface/select/building/sel_universal.xml</select>
    8686      <constructed>interface/complete/building/complete_universal.xml</constructed>
    8787      <death>attack/destruction/building_collapse_large.xml</death>
     88      <attacked>interface/alarm/alarm_attackplayer.xml</attacked>   
    8889    </SoundGroups>
    8990  </Sound>
    9091  <StatusBars>
  • binaries/data/mods/public/simulation/templates/template_unit_cavalry.xml

     
    7979      <walk>actor/mounted/movement/walk.xml</walk>
    8080      <run>actor/mounted/movement/walk.xml</run>
    8181      <attack>attack/weapon/sword.xml</attack>
     82      <attacked>interface/alarm/alarm_attackplayer.xml</attacked>
    8283      <death>actor/fauna/death/death_horse.xml</death>
    8384      <trained>interface/alarm/alarm_create_cav.xml</trained>
    8485    </SoundGroups>
  • binaries/data/mods/public/simulation/templates/template_unit_champion.xml

     
    1414    <stone>0</stone>
    1515    <metal>20</metal>
    1616  </Loot>
     17  <Sound>
     18    <SoundGroups>
     19      <attacked>interface/alarm/alarm_attackplayer.xml</attacked>
     20    </SoundGroups>
     21  </Sound>
    1722</Entity>
  • binaries/data/mods/public/simulation/templates/template_unit_hero.xml

     
    6060  <Sound>
    6161    <SoundGroups>
    6262      <attack>attack/weapon/sword.xml</attack>
     63      <attacked>interface/alarm/alarm_attackplayer.xml</attacked>
    6364      <death>actor/human/death/death.xml</death>
    6465    </SoundGroups>
    6566  </Sound>
  • binaries/data/mods/public/simulation/templates/template_unit_infantry.xml

     
    9292  <Sound>
    9393    <SoundGroups>
    9494      <select>voice/hellenes/civ/civ_male_select.xml</select>
     95      <attacked>interface/alarm/alarm_attackplayer.xml</attacked>
    9596      <order_walk>voice/hellenes/civ/civ_male_ack.xml</order_walk>
    9697      <order_attack>voice/hellenes/civ/civ_male_attack.xml</order_attack>
    9798      <order_gather>voice/hellenes/civ/civ_male_ack.xml</order_gather>
  • binaries/data/mods/public/simulation/templates/template_unit_mechanical.xml

     
    2121    <stone>0</stone>
    2222    <metal>25</metal>
    2323  </Loot>
     24  <Sound>
     25    <SoundGroups>
     26      <attacked>interface/alarm/alarm_attackplayer.xml</attacked>
     27    </SoundGroups>
     28  </Sound>
    2429</Entity>
  • binaries/data/mods/public/simulation/templates/template_unit_support.xml

     
    2323  <Sound>
    2424    <SoundGroups>
    2525      <trained>interface/alarm/alarm_create_worker.xml</trained>
     26      <attacked>interface/alarm/alarm_attackplayer.xml</attacked>
    2627    </SoundGroups>
    2728  </Sound>
    2829  <UnitAI>
  • source/gui/MiniMap.cpp

     
    1 /* Copyright (C) 2012 Wildfire Games.
     1/* Copyright (C) 2013 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    3535#include "ps/Game.h"
    3636#include "ps/Profile.h"
    3737#include "ps/World.h"
     38#include "ps/CLogger.h" //added, remove before commit
    3839#include "renderer/Renderer.h"
    3940#include "renderer/WaterManager.h"
    4041#include "scriptinterface/ScriptInterface.h"
     
    6970        m_ShallowPassageHeight = pathingSettings.GetChild("default").GetChild("MaxWaterDepth").ToFloat();
    7071    else
    7172        m_ShallowPassageHeight = 0.0f;
     73
     74    m_ChangePingColor = 0;
    7275}
    7376
    7477CMiniMap::~CMiniMap()
     
    469472                v.a = 255;
    470473                v.x = posX.ToFloat()*sx;
    471474                v.y = -posZ.ToFloat()*sy;
     475
     476                // Check minimap pinging to indicate something
     477                if (cmpMinimap->IsEntityPinging()) {
     478
     479                    // Override the normal rendering of the entity with the ping color
     480                    // Note: If the pinged entity's dot is rendered over by another entity's
     481                    // dot then it will be invisible & the ping will be not be seen.
     482                    // We can try to move the pinged dots towards the end in the vertexArray
     483                    // Keep 2 pointers and insert pinged dots at end, unpinged at current position
     484                    if (m_ChangePingColor > PING_DURATION/2) {
     485                        v.r = 255; // bright red
     486                        v.g = 1;
     487                        v.b = 1;
     488                    }
     489
     490                    // Must reduce ping count every frame
     491                    u32 pingCount = cmpMinimap->GetRemainingPingCount();
     492                    if (pingCount <= 0) {
     493                        // Also turns off ping flag if 0 passed in
     494                        cmpMinimap->SetRemainingPingCount(0);
     495                    }
     496                    else {
     497                        cmpMinimap->SetRemainingPingCount(pingCount - 1);
     498                    }
     499                }
     500
    472501                vertexArray.push_back(v);
    473502            }
    474503        }
    475504    }
    476505
     506    // Cycle the ping color counter as needed
     507    m_ChangePingColor = (m_ChangePingColor + 1) > PING_DURATION ? 0 : (m_ChangePingColor + 1);
     508
    477509    if (!vertexArray.empty())
    478510    {
    479511        glEnableClientState(GL_VERTEX_ARRAY);
     
    497529    }
    498530
    499531    PROFILE_END("minimap units");
    500    
     532
    501533    if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
    502534    {
    503535        tech->EndPass();
     
    629661    }
    630662
    631663    delete[] m_TerrainData;
    632     m_TerrainData = 0;
     664    m_TerrainData = 0; 
    633665}
  • source/gui/MiniMap.h

     
    1 /* Copyright (C) 2012 Wildfire Games.
     1/* Copyright (C) 2013 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    1818#ifndef INCLUDED_MINIMAP
    1919#define INCLUDED_MINIMAP
    2020
     21// gui
    2122#include "gui/GUI.h"
    2223
     24// Types
     25#include "simulation2/system/Entity.h"
     26
    2327class CCamera;
    2428class CTerrain;
    2529
     30// Pinging constants - Controls blink duration of the ping, smaller means higher ping frequency
     31const unsigned int PING_DURATION = 50;
     32
    2633class CMiniMap : public IGUIObject
    2734{
    2835    GUI_OBJECT(CMiniMap)
    2936public:
    3037    CMiniMap();
    3138    virtual ~CMiniMap();
     39
    3240protected:
    3341    virtual void Draw();
    3442
     
    8189    // maximal water height to allow the passage of a unit (for underwater shallows).
    8290    float m_ShallowPassageHeight;
    8391
     92    // For tracking the ping color
     93    u32 m_ChangePingColor;
     94
    8495    void DrawTexture(float coordMax, float angle, float x, float y, float x2, float y2, float z);
    8596
    8697    void DrawViewRect();
  • source/simulation2/components/CCmpMinimap.cpp

     
    1 /* Copyright (C) 2012 Wildfire Games.
     1/* Copyright (C) 2013 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    2525#include "simulation2/MessageTypes.h"
    2626
    2727#include "ps/Overlay.h"
     28#include "ps/Game.h"
    2829
    2930class CCmpMinimap : public ICmpMinimap
    3031{
     
    3334    {
    3435        componentManager.SubscribeToMessageType(MT_PositionChanged);
    3536        componentManager.SubscribeToMessageType(MT_OwnershipChanged);
     37        componentManager.SubscribeToMessageType(MT_EntityAttacked);
    3638    }
    3739
    3840    DEFAULT_COMPONENT_ALLOCATOR(Minimap)
     
    4850    bool m_Active;
    4951    entity_pos_t m_X, m_Z; // cache the latest position for more efficient rendering; only valid when m_Active true
    5052
     53
     54    // Used by the minimap while pinging this entity to indicate something(currently an attack)
     55    // Entity not pinged after MAX_PING_TURNS if it wasn't notified in between
     56    static const u32 MAX_PING_FRAMES = 500;
     57    bool m_PingEntity;
     58    u32 m_PingCount;
     59
     60
     61
    5162    static std::string GetSchema()
    5263    {
    5364        return
     
    8293    virtual void Init(const CParamNode& paramNode)
    8394    {
    8495        m_Active = true;
     96        m_PingEntity = false;
    8597
    8698        const CParamNode& colour = paramNode.GetChild("Colour");
    8799        if (colour.IsOk())
     
    140152    {
    141153        switch (msg.GetType())
    142154        {
    143         case MT_PositionChanged:
    144         {
    145             const CMessagePositionChanged& data = static_cast<const CMessagePositionChanged&> (msg);
     155            case MT_PositionChanged:
     156            {
     157                const CMessagePositionChanged& data = static_cast<const CMessagePositionChanged&> (msg);
    146158
    147             if (data.inWorld)
    148             {
    149                 m_Active = true;
    150                 m_X = data.x;
    151                 m_Z = data.z;
     159                if (data.inWorld)
     160                {
     161                    m_Active = true;
     162                    m_X = data.x;
     163                    m_Z = data.z;
     164                }
     165                else
     166                {
     167                    m_Active = false;
     168                }
     169
     170                break;
    152171            }
    153             else
     172
     173            case MT_OwnershipChanged:
    154174            {
    155                 m_Active = false;
    156             }
     175                if (!m_UsePlayerColour)
     176                    break;
    157177
    158             break;
    159         }
    160         case MT_OwnershipChanged:
    161         {
    162             if (!m_UsePlayerColour)
    163                 break;
     178                const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg);
    164179
    165             const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg);
     180                // If there's no new owner (e.g. the unit is dying) then don't try updating the colour
     181                if (msgData.to == -1)
     182                    break;
    166183
    167             // If there's no new owner (e.g. the unit is dying) then don't try updating the colour
    168             if (msgData.to == -1)
     184                // Find the new player's colour
     185                CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY);
     186                if (!cmpPlayerManager)
     187                    break;
     188                CmpPtr<ICmpPlayer> cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(msgData.to));
     189                if (!cmpPlayer)
     190                    break;
     191                CColor colour = cmpPlayer->GetColour();
     192                m_R = (u8)(colour.r*255.0);
     193                m_G = (u8)(colour.g*255.0);
     194                m_B = (u8)(colour.b*255.0);
     195                // TODO: probably should avoid using floating-point here
     196
    169197                break;
     198            }
    170199
    171             // Find the new player's colour
    172             CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY);
    173             if (!cmpPlayerManager)
     200            case MT_EntityAttacked:
     201            {
     202                const CMessageEntityAttacked& data = static_cast<const CMessageEntityAttacked&> (msg);
     203
     204                if (!g_Game)
     205                    break;
     206
     207                if(g_Game->GetPlayerID() != (int)data.player)
     208                    break;
     209
     210                m_Active = true;
     211                m_PingEntity = true;
     212                m_PingCount = MAX_PING_FRAMES;
     213
    174214                break;
    175             CmpPtr<ICmpPlayer> cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(msgData.to));
    176             if (!cmpPlayer)
    177                 break;
    178             CColor colour = cmpPlayer->GetColour();
    179             m_R = (u8)(colour.r*255.0);
    180             m_G = (u8)(colour.g*255.0);
    181             m_B = (u8)(colour.b*255.0);
    182             // TODO: probably should avoid using floating-point here
    183 
    184             break;
     215            }
    185216        }
    186         }
    187217    }
    188218
    189219    virtual bool GetRenderData(u8& r, u8& g, u8& b, entity_pos_t& x, entity_pos_t& z)
     
    198228        z = m_Z;
    199229        return true;
    200230    }
     231
     232    virtual bool IsEntityPinging(void)
     233    {
     234        if (!m_Active)
     235            return false;
     236
     237        return m_PingEntity;
     238    }
     239
     240    virtual u32 GetRemainingPingCount(void)
     241    {
     242        return m_PingCount;
     243    }
     244
     245    virtual void SetRemainingPingCount(u32 pingCount)
     246    {
     247        m_PingCount = pingCount;
     248
     249        if (m_PingCount == 0)
     250            m_PingEntity = false;
     251    }
    201252};
    202253
    203254REGISTER_COMPONENT_TYPE(Minimap)
  • source/simulation2/components/ICmpMinimap.h

     
    3535     */
    3636    virtual bool GetRenderData(u8& r, u8& g, u8& b, entity_pos_t& x, entity_pos_t& z) = 0;
    3737
     38    /**
     39     * Returns true if the unit is pinging.
     40     */
     41    virtual bool IsEntityPinging(void) = 0;
     42
     43    /**
     44     * Returns the current ping count.
     45     */
     46    virtual u32 GetRemainingPingCount(void) = 0;
     47
     48    /**
     49     * Used by the minimap to set the ping count, controls pinging.
     50     */
     51    virtual void SetRemainingPingCount(u32 pingCount) = 0;
     52
    3853    DECLARE_INTERFACE_TYPE(Minimap)
    3954};
    4055
  • source/simulation2/MessageTypes.h

     
    398398    entity_pos_t newRange;
    399399};
    400400
     401/**
     402 * Sent when an entity is attacked
     403 */
     404class CMessageEntityAttacked : public CMessage
     405{
     406public:
     407    DEFAULT_MESSAGE_IMPL(EntityAttacked)
     408
     409    CMessageEntityAttacked(entity_id_t entity, entity_id_t player) :
     410    entity(entity), player(player)
     411    {
     412    }
     413
     414    entity_id_t entity;
     415    entity_id_t player;
     416};
     417
    401418#endif // INCLUDED_MESSAGETYPES
  • source/simulation2/scripting/MessageTypeConversions.cpp

     
    336336    return new CMessageVisionRangeChanged(entity, oldRange, newRange);
    337337}
    338338
     339////////////////////////////////
     340
     341jsval CMessageEntityAttacked::ToJSVal(ScriptInterface& scriptInterface) const
     342{
     343    TOJSVAL_SETUP();
     344    SET_MSG_PROPERTY(entity);
     345    SET_MSG_PROPERTY(player);
     346    return OBJECT_TO_JSVAL(obj);
     347}
     348
     349CMessage* CMessageEntityAttacked::FromJSVal(ScriptInterface& scriptInterface, jsval val)
     350{
     351    FROMJSVAL_SETUP();
     352    GET_MSG_PROPERTY(entity_id_t, entity);
     353    GET_MSG_PROPERTY(entity_id_t, player);
     354    return new CMessageEntityAttacked(entity, player);
     355}
     356
    339357////////////////////////////////////////////////////////////////
    340358
    341359CMessage* CMessageFromJSVal(int mtid, ScriptInterface& scriptingInterface, jsval val)
  • source/simulation2/TypeList.h

     
    4949MESSAGE(PathResult)
    5050MESSAGE(TechnologyModification)
    5151MESSAGE(VisionRangeChanged)
     52MESSAGE(EntityAttacked)
    5253
    5354// TemplateManager must come before all other (non-test) components,
    5455// so that it is the first to be (de)serialized