Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_AttackTaskEntity.c
Go to the documentation of this file.
4
5class SCR_AttackTaskEntity : SCR_Task
6{
7 protected const int PERIODICAL_CHECK_INTERVAL = 2000; // ms
8
9 [Attribute("150", UIWidgets.EditBox, "Area radius [m]", "0 inf")]
10 protected float m_fAreaRadius;
11
12 [Attribute("60", UIWidgets.EditBox, "Reset timer to this time [s] when task is activated by player or by killing enemy", "0 inf")]
13 protected float m_fEvaluationTime;
14
15 [Attribute("120", UIWidgets.EditBox, "Time [s] since activation when a task can fail", "0 inf")]
16 protected float m_fFailSafeTime;
17
18 [Attribute("10", UIWidgets.EditBox, "Bonus xp for enemy killed when task is completed", "0 inf")]
20
21 [Attribute("5", UIWidgets.EditBox, "Bonus xp for enemy killed when task is failed", "0 inf")]
23
26 protected float m_fAreaRadiusSq;
27 protected int m_iKilledEnemies;
29 protected ref array<int> m_aCombatPlayerList = {};
30 protected ref array<int> m_aRewardPlayerList = {};
31 protected bool m_bWasActivated;
32 protected RplComponent m_RplComponent;
33
34 //------------------------------------------------------------------------------------------------
35 protected void PeriodicalCheck()
36 {
37 PlayerManager playerManager = GetGame().GetPlayerManager();
38 SCR_ChimeraCharacter character;
39 CharacterControllerComponent charControl;
40 array<int> assigneePlayerIDs = GetTaskAssigneePlayerIDs();
41 if (!assigneePlayerIDs)
42 return;
43
44 ChimeraWorld world = GetGame().GetWorld();
45 if (!world)
46 return;
47
48 bool isAnyAssignedPlayerInZone = false;
49 foreach (int playerId : assigneePlayerIDs)
50 {
51 character = SCR_ChimeraCharacter.Cast(playerManager.GetPlayerControlledEntity(playerId));
52 if (!character)
53 continue;
54
55 charControl = character.GetCharacterController();
56 if (!charControl || charControl.IsDead())
57 continue;
58
59 if (vector.DistanceSqXZ(character.GetOrigin(), GetTaskPosition()) > m_fAreaRadiusSq)
60 continue;
61
62 RegisterPlayer(playerId);
63
64 if (!m_bWasActivated)
65 {
66 m_TaskActivatedTimestamp = world.GetServerTimestamp();
67 m_EvaluationTimestamp = world.GetServerTimestamp().PlusSeconds(m_fEvaluationTime);
68 m_bWasActivated = true;
69 #ifdef ATTACK_TASK_DEBUG
70 Print("Attack task, task activated", LogLevel.DEBUG);
71 #endif
72 }
73
74 isAnyAssignedPlayerInZone = true;
75 }
76
77 if (!m_bWasActivated)
78 return;
79
80 // no one was killed and a player from the assigned group left the zone => reset evaluation timer
81 if (m_iKilledEnemies == 0 && m_iKilledAssignedPlayers == 0 && !isAnyAssignedPlayerInZone)
82 m_EvaluationTimestamp = world.GetServerTimestamp().PlusSeconds(m_fEvaluationTime);
83
84 WorldTimestamp currentTime = world.GetServerTimestamp();
85
86 #ifdef ATTACK_TASK_DEBUG
87 PrintFormat("Attack task, finish remaining time:%1, timeFromStart:%2", m_EvaluationTimestamp.DiffSeconds(currentTime), m_TaskActivatedTimestamp.DiffSeconds(currentTime), level: LogLevel.DEBUG);
88 #endif
89
90 if (currentTime.Less(m_EvaluationTimestamp))
91 return;
92
93 if (!m_aCombatPlayerList.IsEmpty())
94 {
95 #ifdef ATTACK_TASK_DEBUG
96 Print("Attack task, completed", LogLevel.DEBUG);
97 #endif
98
99 m_TaskSystem.SetTaskState(this, SCR_ETaskState.COMPLETED);
100 DeleteTask();
101 }
102 else if (currentTime.GreaterEqual(m_TaskActivatedTimestamp.PlusSeconds(m_fFailSafeTime)))
103 {
104 #ifdef ATTACK_TASK_DEBUG
105 Print("Attack task, failed", LogLevel.DEBUG);
106 #endif
107
108 m_TaskSystem.SetTaskState(this, SCR_ETaskState.FAILED);
109 DeleteTask();
110 }
111 }
112
113 //------------------------------------------------------------------------------------------------
114 protected void OnControllableDestroyed(notnull SCR_InstigatorContextData instigatorContextData)
115 {
116 bool wasAssignedPlayerKilled;
117
118 // remove a player from the combat list if he dies
119 if (m_aCombatPlayerList.Contains(instigatorContextData.GetVictimPlayerID()))
120 {
121 m_aCombatPlayerList.RemoveItem(instigatorContextData.GetVictimPlayerID());
122 wasAssignedPlayerKilled = true;
123
124 #ifdef ATTACK_TASK_DEBUG
125 PrintFormat("Attack task, playerID:%1 was killed and removed from combat list", instigatorContextData.GetVictimPlayerID(), level: LogLevel.DEBUG);
126 #endif
127 }
128
129 // check if was killed by enemy
130 if (!instigatorContextData.HasAnyVictimKillerRelation(SCR_ECharacterDeathStatusRelations.KILLED_BY_ENEMY_PLAYER | SCR_ECharacterDeathStatusRelations.KILLED_BY_ENEMY_AI))
131 return;
132
133 IEntity victimEntity = instigatorContextData.GetVictimEntity();
134 if (!victimEntity)
135 return;
136
137 IEntity killerEntity = instigatorContextData.GetKillerEntity();
138 if (!killerEntity)
139 return;
140
141 // player from assigned group was killed by enemy
142 if (wasAssignedPlayerKilled)
143 {
145
146 #ifdef ATTACK_TASK_DEBUG
147 PrintFormat("Attack task, playerID:%1 was killed by enemy", instigatorContextData.GetVictimPlayerID(), level: LogLevel.DEBUG);
148 #endif
149 }
150
151 // check distance from task, if killer or victim is in radius, it's count as kill
152 if (vector.DistanceSq(GetTaskPosition(), victimEntity.GetOrigin()) > m_fAreaRadiusSq &&
153 vector.DistanceSq(GetTaskPosition(), killerEntity.GetOrigin()) > m_fAreaRadiusSq)
154 return;
155
156 // get faction from entity(player, AI)
157 Faction killerFaction = SCR_Faction.GetEntityFaction(killerEntity);
158 array<string> ownerFactionKeys = GetOwnerFactionKeys();
159 if (!ownerFactionKeys || !ownerFactionKeys.Contains(killerFaction.GetFactionKey()))
160 return;
161
162 SCR_GroupsManagerComponent groupManager = SCR_GroupsManagerComponent.GetInstance();
163 if (!groupManager)
164 return;
165
166 SCR_AIGroup group;
167 int killerId = instigatorContextData.GetKillerPlayerID();
168 if (killerId <= 0)
169 {
170 // killer is AI
171 AIControlComponent aiControlComponent = AIControlComponent.Cast(killerEntity.FindComponent(AIControlComponent));
172 if (!aiControlComponent)
173 return;
174
175 AIAgent agent = aiControlComponent.GetAIAgent();
176 if (!agent)
177 return;
178
179 group = SCR_AIGroup.Cast(agent);
180 if (!group)
181 group = SCR_AIGroup.Cast(agent.GetParentGroup());
182
183 if (!group || !group.IsSlave() || !group.GetMaster())
184 return;
185
186 group = group.GetMaster();
187 }
188 else
189 {
190 // killer is player
191 group = groupManager.GetPlayerGroup(killerId);
192 }
193
194 if (!group)
195 return;
196
197 // check if killer's group(could be master) is assigned in the task
198 int killerPlayerGroup = group.GetGroupID();
199 if (!IsTaskAssignedTo(SCR_TaskExecutor.FromGroup(killerPlayerGroup)))
200 return;
201
202 // when AI group kill enemy, leader will get into combat list
203 killerId = group.GetLeaderID();
204
205 #ifdef ATTACK_TASK_DEBUG
206 Print("Attack task, somebody was killed in the zone, timer was reset", LogLevel.DEBUG);
207 #endif
208
209 // somebody was killed(player, AI) in the zone => reset combat timer
210 ChimeraWorld world = GetGame().GetWorld();
211 if (world)
212 {
213 m_EvaluationTimestamp = world.GetServerTimestamp().PlusSeconds(m_fEvaluationTime);
214 if (!m_bWasActivated)
215 m_TaskActivatedTimestamp = world.GetServerTimestamp();
216 }
217
218 m_bWasActivated = true;
220
221 if (killerId > 0)
222 RegisterPlayer(killerId);
223 }
224
225 //------------------------------------------------------------------------------------------------
226 protected void RegisterPlayer(int playerId)
227 {
228 if (!m_aCombatPlayerList.Contains(playerId))
229 {
230 m_aCombatPlayerList.Insert(playerId);
231
232 #ifdef ATTACK_TASK_DEBUG
233 Print("Attack task, playerId"+playerId+" is registered to combat list", LogLevel.DEBUG);
234 #endif
235 }
236
237 if (!m_aRewardPlayerList.Contains(playerId))
238 m_aRewardPlayerList.Insert(playerId);
239 }
240
241 //------------------------------------------------------------------------------------------------
242 protected void AddXPReward(SCR_ETaskState state)
243 {
244 if (state != SCR_ETaskState.COMPLETED && state != SCR_ETaskState.FAILED)
245 return;
246
247 SCR_XPHandlerComponent xpHandler = SCR_XPHandlerComponent.Cast(GetGame().GetGameMode().FindComponent(SCR_XPHandlerComponent));
248 if (!xpHandler || !m_RplComponent || m_RplComponent.IsProxy())
249 return;
250
251 // add XP to all players in the assigned group
252 array<int> assigneePlayerIDs = GetTaskAssigneePlayerIDs();
253 if (!assigneePlayerIDs)
254 return;
255
256 int bonusXp = m_iKilledEnemies;
257 SCR_EXPRewards xpRewardType;
258
259 if (state == SCR_ETaskState.COMPLETED)
260 {
261 xpRewardType = SCR_EXPRewards.ATTACK_TASK_COMPLETED;
263 }
264 else if (state == SCR_ETaskState.FAILED)
265 {
266 xpRewardType = SCR_EXPRewards.ATTACK_TASK_FAILED;
268 }
269
270 int taskXp = xpHandler.GetXPRewardAmount(xpRewardType);
271 if (taskXp <= 0)
272 return;
273
274 float bonusMultiplier = 1 + (bonusXp / taskXp);
275
276 foreach (int playerID : assigneePlayerIDs)
277 {
278 if (m_aRewardPlayerList.Contains(playerID))
279 {
280 xpHandler.AwardXP(playerID, xpRewardType, bonusMultiplier, false);
281
282 #ifdef ATTACK_TASK_DEBUG
283 PrintFormat("Attack task, player:%1 is rewarded, taskXp:%2, bonusXp:%3 for killed enemies:%4", playerID, taskXp, bonusXp, m_iKilledEnemies, level: LogLevel.DEBUG);
284 #endif
285 }
286 }
287 }
288
289 //------------------------------------------------------------------------------------------------
290 override void SetTaskState(SCR_ETaskState state)
291 {
292 AddXPReward(state);
293
294 super.SetTaskState(state);
295 }
296
297 //------------------------------------------------------------------------------------------------
298 protected void DeleteTask()
299 {
300 if (!m_TaskSystem)
301 return;
302
303 m_TaskSystem.DeleteTask(this);
304 }
305
306 //------------------------------------------------------------------------------------------------
307 override void EOnInit(IEntity owner)
308 {
309 super.EOnInit(owner);
310
311 if (SCR_Global.IsEditMode(this))
312 return;
313
315 if (!gameMode)
316 return;
317
319 m_RplComponent = RplComponent.Cast(owner.FindComponent(RplComponent));
320
321 if (!m_RplComponent || m_RplComponent.IsProxy())
322 return;
323
324 GetGame().GetCallqueue().CallLater(PeriodicalCheck, PERIODICAL_CHECK_INTERVAL, true);
326 }
327
328 //------------------------------------------------------------------------------------------------
330 {
331 GetGame().GetCallqueue().Remove(PeriodicalCheck);
332
334 if (!gameMode)
335 return;
336
338 }
339}
ArmaReforgerScripted GetGame()
Definition game.c:1398
ref array< int > m_aCombatPlayerList
int m_iKilledEnemies
void DeleteTask()
void PeriodicalCheck()
ref array< int > m_aRewardPlayerList
array of playerIDs
bool m_bWasActivated
array of playerIDs
WorldTimestamp m_EvaluationTimestamp
override void SetTaskState(SCR_ETaskState state)
void ~SCR_AttackTaskEntity()
float m_fEvaluationTime
float m_fFailSafeTime
float m_fAreaRadius
WorldTimestamp m_TaskActivatedTimestamp
SCR_AttackTaskEntityClass PERIODICAL_CHECK_INTERVAL
int m_iKilledAssignedPlayers
int m_iEnemyKillBonusXp_TaskFailed
float m_fAreaRadiusSq
int m_iEnemyKillBonusXp_TaskCompleted
SCR_BaseGameMode GetGameMode()
RplComponent m_RplComponent
void AddXPReward()
void SCR_GroupsManagerComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
void OnControllableDestroyed(IEntity entity, IEntity killerEntity, Instigator instigator, notnull SCR_InstigatorContextData instigatorContextData)
void RegisterPlayer(int iPlayerID, IEntity playerEntity)
array< int > GetTaskAssigneePlayerIDs()
Definition SCR_Task.c:458
vector GetTaskPosition()
Definition SCR_Task.c:1282
void SCR_Task(IEntitySource src, IEntity parent)
Definition SCR_Task.c:1938
array< string > GetOwnerFactionKeys()
Definition SCR_Task.c:951
SCR_ETaskState
Definition SCR_Task.c:3
bool IsTaskAssignedTo(SCR_TaskExecutor executor, out SCR_TaskExecutor match=null)
Definition SCR_Task.c:493
SCR_TaskSystem m_TaskSystem
proto external Managed FindComponent(typename typeName)
proto external vector GetOrigin()
SCR_AIGroup GetMaster()
int GetGroupID()
bool IsSlave()
int GetLeaderID()
ScriptInvokerBase< SCR_BaseGameMode_OnControllableDestroyed > GetOnControllableDestroyed()
static Faction GetEntityFaction(notnull IEntity entity)
static bool IsEditMode()
Definition Functions.c:1566
override void EOnInit(IEntity owner)
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
proto void PrintFormat(string fmt, void param1=NULL, void param2=NULL, void param3=NULL, void param4=NULL, void param5=NULL, void param6=NULL, void param7=NULL, void param8=NULL, void param9=NULL, LogLevel level=LogLevel.NORMAL)
SCR_FieldOfViewSettings Attribute