Line data Source code
1 : function VisionSharing() {}
2 :
3 1 : VisionSharing.prototype.Schema =
4 : "<element name='Bribable'>" +
5 : "<data type='boolean'/>" +
6 : "</element>" +
7 : "<optional>" +
8 : "<element name='Duration' a:help='Duration (in second) of the vision sharing for spies'>" +
9 : "<ref name='positiveDecimal'/>" +
10 : "</element>" +
11 : "</optional>" +
12 : "<optional>" +
13 : "<element name='FailureCostRatio' a:help='Fraction of the bribe cost that will be incured if a bribe failed'>" +
14 : "<ref name='nonNegativeDecimal'/>" +
15 : "</element>" +
16 : "</optional>";
17 :
18 1 : VisionSharing.prototype.Init = function()
19 : {
20 1 : this.activated = false;
21 1 : this.shared = undefined;
22 1 : this.spyId = 0;
23 1 : this.spies = undefined;
24 : };
25 :
26 : /**
27 : * As entities have not necessarily the VisionSharing component, it has to be activated
28 : * before use so that the rangeManager can register it
29 : */
30 1 : VisionSharing.prototype.Activate = function()
31 : {
32 6 : if (this.activated)
33 5 : return;
34 1 : let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
35 1 : if (!cmpOwnership || cmpOwnership.GetOwner() <= 0)
36 0 : return;
37 1 : this.shared = new Set([cmpOwnership.GetOwner()]);
38 1 : Engine.PostMessage(this.entity, MT_VisionSharingChanged,
39 : { "entity": this.entity, "player": cmpOwnership.GetOwner(), "add": true });
40 1 : this.activated = true;
41 : };
42 :
43 1 : VisionSharing.prototype.CheckVisionSharings = function()
44 : {
45 6 : let shared = new Set();
46 :
47 6 : let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
48 6 : let owner = cmpOwnership ? cmpOwnership.GetOwner() : INVALID_PLAYER;
49 6 : if (owner >= 0)
50 : {
51 : // The owner has vision
52 6 : if (owner > 0)
53 6 : shared.add(owner);
54 :
55 : // Vision sharing due to garrisoned units
56 6 : let cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
57 6 : if (cmpGarrisonHolder)
58 : {
59 6 : for (let ent of cmpGarrisonHolder.GetEntities())
60 : {
61 5 : let cmpEntOwnership = Engine.QueryInterface(ent, IID_Ownership);
62 5 : if (!cmpEntOwnership)
63 0 : continue;
64 5 : let entOwner = cmpEntOwnership.GetOwner();
65 5 : if (entOwner > 0 && entOwner != owner)
66 : {
67 3 : shared.add(entOwner);
68 : // if shared by another player than the owner and not yet activated, do it
69 3 : this.Activate();
70 : }
71 : }
72 : }
73 :
74 : // vision sharing due to spies
75 6 : if (this.spies)
76 3 : for (let spy of this.spies.values())
77 7 : if (spy > 0 && spy != owner)
78 7 : shared.add(spy);
79 : }
80 :
81 6 : if (!this.activated)
82 0 : return;
83 :
84 : // compare with previous vision sharing, and update if needed
85 6 : for (let player of shared)
86 16 : if (!this.shared.has(player))
87 3 : Engine.PostMessage(this.entity, MT_VisionSharingChanged,
88 : { "entity": this.entity, "player": player, "add": true });
89 6 : for (let player of this.shared)
90 15 : if (!shared.has(player))
91 2 : Engine.PostMessage(this.entity, MT_VisionSharingChanged,
92 : { "entity": this.entity, "player": player, "add": false });
93 6 : this.shared = shared;
94 : };
95 :
96 1 : VisionSharing.prototype.IsBribable = function()
97 : {
98 4 : return this.template.Bribable == "true";
99 : };
100 :
101 1 : VisionSharing.prototype.OnGarrisonedUnitsChanged = function(msg)
102 : {
103 0 : this.CheckVisionSharings();
104 : };
105 :
106 1 : VisionSharing.prototype.OnOwnershipChanged = function(msg)
107 : {
108 0 : if (this.activated)
109 0 : this.CheckVisionSharings();
110 : };
111 :
112 1 : VisionSharing.prototype.AddSpy = function(player, timeLength)
113 : {
114 3 : if (!this.IsBribable())
115 0 : return 0;
116 :
117 3 : let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
118 3 : if (!cmpOwnership || cmpOwnership.GetOwner() == player || player <= 0)
119 0 : return 0;
120 :
121 3 : let cmpTechnologyManager = QueryPlayerIDInterface(player, IID_TechnologyManager);
122 3 : if (!cmpTechnologyManager || !cmpTechnologyManager.CanProduce("special/spy"))
123 0 : return 0;
124 :
125 3 : let template = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager).GetTemplate("special/spy");
126 3 : if (!IncurBribeCost(template, player, cmpOwnership.GetOwner(), false))
127 1 : return 0;
128 :
129 : // If no duration given, take it from the spy template and scale it with the ent vision
130 : // When no duration argument nor in spy template, it is a permanent spy
131 2 : let duration = timeLength;
132 2 : if (!duration && template.VisionSharing && template.VisionSharing.Duration)
133 : {
134 1 : duration = ApplyValueModificationsToTemplate("VisionSharing/Duration", +template.VisionSharing.Duration, player, template);
135 1 : let cmpVision = Engine.QueryInterface(this.entity, IID_Vision);
136 1 : if (cmpVision)
137 1 : duration *= 60 / Math.max(30, cmpVision.GetRange());
138 : }
139 :
140 2 : if (!this.spies)
141 0 : this.spies = new Map();
142 :
143 2 : this.spies.set(++this.spyId, player);
144 2 : if (duration)
145 : {
146 2 : let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
147 2 : cmpTimer.SetTimeout(this.entity, IID_VisionSharing, "RemoveSpy", duration * 1000, { "id": this.spyId });
148 : }
149 2 : this.Activate();
150 2 : this.CheckVisionSharings();
151 :
152 : // update statistics for successful bribes
153 2 : let cmpBribesStatisticsTracker = QueryPlayerIDInterface(player, IID_StatisticsTracker);
154 2 : if (cmpBribesStatisticsTracker)
155 0 : cmpBribesStatisticsTracker.IncreaseSuccessfulBribesCounter();
156 :
157 2 : return this.spyId;
158 : };
159 :
160 1 : VisionSharing.prototype.RemoveSpy = function(data)
161 : {
162 1 : this.spies.delete(data.id);
163 1 : this.CheckVisionSharings();
164 : };
165 :
166 : /**
167 : * Returns true if this entity share its vision with player
168 : */
169 1 : VisionSharing.prototype.ShareVisionWith = function(player)
170 : {
171 6 : if (this.activated)
172 4 : return this.shared.has(player);
173 :
174 2 : let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
175 2 : return cmpOwnership && cmpOwnership.GetOwner() == player;
176 : };
177 :
178 1 : Engine.RegisterComponentType(IID_VisionSharing, "VisionSharing", VisionSharing);
|