DayZ 1.24
Loading...
Searching...
No Matches
Watchtower.c
Go to the documentation of this file.
1class Watchtower extends BaseBuildingBase
2{
3 typename ATTACHMENT_BARBED_WIRE = BarbedWire;
4 typename ATTACHMENT_CAMONET = CamoNet;
5
6 const float MAX_FLOOR_VERTICAL_DISTANCE = 0.5;
7
8 const float MIN_ACTION_DETECTION_ANGLE_RAD = 0.35; //0.35 RAD = 20 DEG
9 const float MAX_ACTION_DETECTION_DISTANCE = 2.0; //meters
10
11 static const string BASE_VIEW_NAME = "level_";
12 static const string BASE_WALL_NAME = "_wall_";
13 static const string BASE_ROOF_NAME = "_roof";
14 static const int MAX_WATCHTOWER_FLOORS = 3;
15 static const int MAX_WATCHTOWER_WALLS = 3;
16
18 {
19 }
20
21 override string GetConstructionKitType()
22 {
23 return "WatchtowerKit";
24 }
25
26 override int GetMeleeTargetType()
27 {
28 return EMeleeTargetType.NONALIGNABLE;
29 }
30
31 /*override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
32 {
33 super.EEHitBy(damageResult, damageType, source, component, dmgZone, ammo, modelPos, speedCoef);
34
35 if (component == -1)
36 {
37 Print("EEHitBy: " + this + "; damageType: "+ damageType +"; source: "+ source +"; component: "+ component +"; dmgZone: "+ dmgZone +"; ammo: "+ ammo +"; modelPos: "+ modelPos);
38 Print("GetDamage " + damageResult.GetDamage("","Health"));
39 Print("GetHighestDamage " + damageResult.GetHighestDamage("Health"));
40 }
41 }*/
42
43 //overriden for the express purpose of handling view geometry (interaction) animations
44 override void UpdateVisuals()
45 {
46 super.UpdateVisuals();
47
48 SetAnimationPhase("level_1", 0); //always visible
49 SetAnimationPhase("level_1_wall_1", 0); //always visible
50 SetAnimationPhase("level_1_wall_2", 0); //always visible
51 SetAnimationPhase("level_1_wall_3", 0); //always visible
52
53 string part_name = "";
54 bool built = false;
55
56 for (int i = 1; i < MAX_WATCHTOWER_FLOORS; ++i)
57 {
58 //roof checks
59 part_name = "" + BASE_VIEW_NAME + i + BASE_ROOF_NAME;
60 built = GetConstruction().IsPartConstructed(part_name);
61 //Print(part_name);
62 //Print(built);
63
64 //string tmp = "";
65
66 if (built)
67 {
68 SetAnimationPhase(BASE_VIEW_NAME + (i + 1), 0); //show
69 for (int j = 1; j < MAX_WATCHTOWER_WALLS + 1; ++j)
70 {
71 //tmp = BASE_VIEW_NAME + (i + 1) + BASE_WALL_NAME + j;
72 //Print(tmp);
73 SetAnimationPhase(BASE_VIEW_NAME + (i + 1) + BASE_WALL_NAME + j, 0); //show
74 }
75 }
76 else
77 {
78 SetAnimationPhase(BASE_VIEW_NAME + (i + 1), 1); //hide
79 for (j = 1; j < MAX_WATCHTOWER_WALLS + 1; ++j)
80 {
81 //tmp = BASE_VIEW_NAME + (i + 1) + BASE_WALL_NAME + j;
82 //Print(tmp);
83 SetAnimationPhase(BASE_VIEW_NAME + (i + 1) + BASE_WALL_NAME + j, 1); //hide
84 }
85 }
86 }
87 }
88
89 //--- ATTACHMENT & CONDITIONS
91 {
92 if (!super.CanReceiveAttachment(attachment, slotId))
93 return false;
94
95 //because CanReceiveAttachment() method can be called on all clients in the vicinity, vertical distance check needs to be skipped on clients that don't
96 //interact with the object through attach action (AT_ATTACH_TO_CONSTRUCTION)
98 if (!GetGame().IsDedicatedServer())
99 {
100 //check action initiator (AT_ATTACH_TO_CONSTRUCTION)
102 if (player)
103 {
104 ConstructionActionData construction_action_data = player.GetConstructionActionData();
106
108 {
109 construction_action_data.SetActionInitiator(NULL); //reset action initiator
110 }
111 else
112 {
113 player = null; //do not do vertical check (next)
114 }
115 }
116 }
117 //
118
120 }
121
122 //can put into hands
123 override bool CanPutIntoHands(EntityAI parent)
124 {
125 return false;
126 }
127
129 {
130 return true;
131 }
132
134 {
136 return false;
137
138 if (partName != "level_1_base" && partName != "level_2_base" && partName != "level_3_base" && partName != "level_3_roof")
139 return false;
140
144 vector min_max[2];
147
148 excluded_objects.Insert(this);
149 excluded_objects.Insert(player);
150
151 if (partName == "level_2_base")
152 {
153 min_max[0] = GetMemoryPointPos("level_2_wall_1_down_min");
154 min_max[1] = GetMemoryPointPos("level_2_roof_max");
155 }
156 else if (partName == "level_3_base")
157 {
158 min_max[0] = GetMemoryPointPos("level_3_wall_1_down_min");
159 min_max[1] = GetMemoryPointPos("level_3_wall_2_up_max");
160 }
161 else if (partName == "level_3_roof")
162 {
163 min_max[0] = GetMemoryPointPos("level_3_roof_min");
164 min_max[1] = GetMemoryPointPos("level_3_roof_max");
165 }
166 else
167 {
168 //min_max[0] = GetMemoryPointPos( "level_1_wall_1_up_min" );
169 //min_max[0] = GetMemoryPointPos( "level_1_wall_1_down_min" );
170 min_max[0] = GetMemoryPointPos("level_1_collisioncheck_min");
171 min_max[1] = GetMemoryPointPos("level_1_roof_max");
172 }
174 center[1] = center[1] + (min_max[1][1] + min_max[0][1]) / 2;
175
176 edge_length[0] = min_max[1][0] - min_max[0][0];
177 edge_length[2] = min_max[1][2] - min_max[0][2];
178 edge_length[1] = min_max[1][1] - min_max[0][1];
179
180 result = false;
182 if (collided_objects.Count() > 0)
183 {
184 foreach (Object o : collided_objects)
185 {
186 if (Building.Cast(o))
187 result = true;
188 }
189 }
190 return true;
191 }
192
193 // --- INVENTORY
195 {
196 //super
197 if (!super.CanDisplayAttachmentSlot(slot_id))
198 return false;
199
201 slot_name.ToLower();
203 //base attachments
204 if (slot_name.Contains("material_l1") || slot_name.Contains("level_1_"))
205 {
206 if (slot_name.Contains("woodenlogs"))
207 return CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player);
208 else
209 return GetConstruction().IsPartConstructed("level_1_base") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player);
210 }
211 else if (slot_name.Contains("material_l2") || slot_name.Contains("level_2_"))
212 {
213 if (slot_name.Contains("woodenlogs"))
214 return CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player);
215 else
216 return GetConstruction().IsPartConstructed("level_2_base") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player);
217 }
218 else if (slot_name.Contains("material_l3") || slot_name.Contains("level_3_"))
219 {
220 if (slot_name.Contains("woodenlogs"))
221 return CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player);
222 else
223 return GetConstruction().IsPartConstructed("level_3_base") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player);
224 }
225
226 return true;
227 }
228
230 {
231 //super
232 if (!super.CanDisplayAttachmentCategory(category_name))
233 return false;
234 //
235
236 category_name.ToLower();
238 //level 1
239 if (category_name.Contains("level_1"))
240 {
241 if (category_name.Contains("level_1_"))
242 return GetConstruction().IsPartConstructed("level_1_base") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player);
243 else
244 return CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player);
245 }
246 //level 2
247 if (category_name.Contains("level_2"))
248 {
249 if (category_name.Contains("level_2_"))
250 return GetConstruction().IsPartConstructed("level_2_base") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player);
251 else
252 return GetConstruction().IsPartConstructed("level_1_roof") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player);
253 }
254 //level 3
255 if (category_name.Contains("level_3"))
256 {
257 if (category_name.Contains("level_3_"))
258 return GetConstruction().IsPartConstructed("level_3_base") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player);
259 else
260 return GetConstruction().IsPartConstructed("level_2_roof") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player);
261 }
262
263 return true;
264 }
265
266 //returns true if attachment slot position is within given range
268 {
269 string slot_name;
271 slot_name.ToLower();
272
273 //wall attachments
274 //level 1
275 if (slot_name.Contains("material_l1") || slot_name.Contains("level_1_"))
276 {
277 if (slot_name.Contains("woodenlogs"))
278 return CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player);
279 else
280 return GetConstruction().IsPartConstructed("level_1_base") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player);
281 }
282 //level 2
283 if (slot_name.Contains("material_l2") || slot_name.Contains("level_2_"))
284 {
285 if (slot_name.Contains("material_l2w") || slot_name.Contains("level_2_wall"))
286 return GetConstruction().IsPartConstructed("level_2_base") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player);
287 else
288 {
289 if (slot_name.Contains("woodenlogs"))
290 return CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player);
291 else
292 return GetConstruction().IsPartConstructed("level_1_roof") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player);
293 }
294 }
295 //level 3
296 if (slot_name.Contains("material_l3") || slot_name.Contains("level_3_"))
297 {
298 if (slot_name.Contains("material_l3w") || slot_name.Contains("level_3_wall"))
299 return GetConstruction().IsPartConstructed("level_3_base") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player);
300 else
301 {
302 if (slot_name.Contains("woodenlogs"))
303 return CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player);
304 else
305 return GetConstruction().IsPartConstructed("level_2_roof") && CheckMemoryPointVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player);
306 }
307 }
308
309 return true;
310 }
311
312 //returns true if player->mem_point position is within given range
313 override bool CheckMemoryPointVerticalDistance(float max_dist, string selection, PlayerBase player)
314 {
315 if (player)
316 {
317 //check vertical distance
318 vector player_pos = player.GetPosition();
319 vector pos;
320
321 if (MemoryPointExists(selection))
322 pos = ModelToWorld(GetMemoryPointPos(selection));
323
324 if (Math.AbsFloat(player_pos[1] - pos[1]) <= max_dist)
325 return true;
326 else
327 return false;
328 }
329
330 return true;
331 }
332
333 override bool CheckLevelVerticalDistance(float max_dist, string selection, PlayerBase player)
334 {
335 if (player)
336 {
337 if (selection.Contains("level_1_"))
339
340 if (selection.Contains("level_2_"))
342
343 if (selection.Contains("level_3_"))
345 }
346 return false;
347 }
348 // ---
349 override void AfterStoreLoad()
350 {
351 super.AfterStoreLoad();
352
354 }
355
356 override void OnPartBuiltServer(notnull Man player, string part_name, int action_id)
357 {
358 super.OnPartBuiltServer(player, part_name, action_id);
359 //update visuals (server)
361 }
362
364 {
365 super.OnPartDismantledServer(player, part_name, action_id);
366 //update visuals (server)
368 }
369
370 override void OnPartDestroyedServer(Man player, string part_name, int action_id, bool destroyed_by_connected_part = false)
371 {
372 super.OnPartDestroyedServer(player, part_name, action_id);
373 //update visuals (server)
375 }
376
377 //--- ACTION CONDITIONS
378 //returns dot product of player->construction direction based on existing/non-existing reference point
379 override bool IsFacingPlayer(PlayerBase player, string selection)
380 {
384 float dot;
385 bool has_memory_point = MemoryPointExists(selection);
386
388 {
389 ref_pos = ModelToWorld(GetMemoryPointPos(selection));
391 }
392 else
393 {
395 ref_dir = ref_pos - player.GetPosition();
396 }
397
398 ref_dir.Normalize();
399 ref_dir[1] = 0; //ignore height
400
401 player_dir = player.GetDirection();
402 player_dir.Normalize();
403 player_dir[1] = 0; //ignore height
404
405 if (ref_dir.Length() != 0)
407
409 {
410 if (dot < 0 && Math.AbsFloat(dot) > MIN_ACTION_DETECTION_ANGLE_RAD)
411 return true;
412 }
413 else
414 {
415 if (dot > 0 && Math.AbsFloat(dot) > MIN_ACTION_DETECTION_ANGLE_RAD)
416 return true;
417 }
418
419 return false;
420 }
421
422 override bool IsFacingCamera(string selection)
423 {
426 vector cam_dir = GetGame().GetCurrentCameraDirection();
427
428 if (MemoryPointExists(selection))
429 {
430 ref_pos = ModelToWorld(GetMemoryPointPos(selection));
432
433 ref_dir.Normalize();
434 ref_dir[1] = 0; //ignore height
435
436 cam_dir[1] = 0; //ignore height
437
438 if (ref_dir.Length() > 0.5) //if the distance (m) is too low, ignore this check
439 {
440 float dot = vector.Dot(cam_dir, ref_dir);
441
442 if (dot < 0)
443 return true;
444 }
445 }
446
447 return false;
448 }
449
450 override bool IsPlayerInside(PlayerBase player, string selection)
451 {
452 if (selection != "")
453 CheckLevelVerticalDistance(MAX_FLOOR_VERTICAL_DISTANCE, selection, player);
454 vector player_pos = player.GetPosition();
456 vector ref_dir = GetDirection();
457 ref_dir[1] = 0;
458 ref_dir.Normalize();
459
460 vector min, max;
461
462 min = -GetMemoryPointPos("interact_min");
463 max = -GetMemoryPointPos("interact_max");
464
466 dir_to_tower[1] = 0;
467 float len = dir_to_tower.Length();
468
469
470 dir_to_tower.Normalize();
471
472 vector ref_dir_angle = ref_dir.VectorToAngles();
473 vector dir_to_tower_angle = dir_to_tower.VectorToAngles();
475
476 vector test_position = test_angles.AnglesToVector() * len;
477
478 if (test_position[0] > max[0] || test_position[0] < min[0] || test_position[2] > max[2] || test_position[2] < min[2])
479 return false;
480
481 return true;
482 }
483
484 override bool HasProperDistance(string selection, PlayerBase player)
485 {
486 if (MemoryPointExists(selection))
487 {
488 vector selection_pos = ModelToWorld(GetMemoryPointPos(selection));
489 float distance = vector.Distance(selection_pos, player.GetPosition());
490 if (distance >= MAX_ACTION_DETECTION_DISTANCE)
491 return false;
492 }
493
494 return true;
495 }
496
497 override void SetActions()
498 {
499 super.SetActions();
500
504 }
505
506
507 //================================================================
508 // DEBUG
509 //================================================================
510
513 {
515
516#ifdef DIAG_DEVELOPER
517 bool bWood = DiagMenu.GetBool(DiagMenuIDs.BASEBUILDING_WOOD);
518#else
519 bool bWood = false;
520#endif
521
522 if (bWood)
523 {
524 excludes = {"_metal_"};
525 }
526 else
527 {
528 excludes = {"_wood_"};
529 }
530
531 return excludes;
532 }
533
534 //Debug menu Spawn Ground Special
535 override void OnDebugSpawn()
536 {
537 super.OnDebugSpawn();
538
539 int i;
540
541 for (i = 0; i < MAX_WATCHTOWER_FLOORS * MAX_WATCHTOWER_WALLS; ++i)
542 GetInventory().CreateInInventory("CamoNet");
543
544 for (i = 0; i < 2 * MAX_WATCHTOWER_WALLS; ++i)
545 {
546 BarbedWire wire = BarbedWire.Cast(GetInventory().CreateInInventory("BarbedWire"));
547 wire.SetMountedState(true);
548 }
549 }
550
551}
ActionFoldBaseBuildingObjectCB ActionContinuousBaseCB ActionFoldBaseBuildingObject()
void AddAction(typename actionName)
vector GetOrientation()
Construction GetConstruction()
DiagMenuIDs
Definition EDiagMenuIDs.c:2
EMeleeTargetType
PlayerBase GetPlayer()
class JsonUndergroundAreaTriggerData GetPosition
override bool CanDisplayAttachmentCategory(string category_name)
Definition Watchtower.c:229
override void OnDebugSpawn()
Definition Watchtower.c:535
override bool IsPlayerInside(PlayerBase player, string selection)
Definition Watchtower.c:450
override bool CanDisplayAttachmentSlot(int slot_id)
Definition Watchtower.c:194
override string GetConstructionKitType()
Definition Watchtower.c:21
static const int MAX_WATCHTOWER_WALLS
Definition Watchtower.c:15
override bool CheckLevelVerticalDistance(float max_dist, string selection, PlayerBase player)
Definition Watchtower.c:333
override bool CanPutIntoHands(EntityAI parent)
Definition Watchtower.c:123
override array< string > OnDebugSpawnBuildExcludes()
Excludes certain parts from being built by OnDebugSpawn, uses Contains to compare.
Definition Watchtower.c:512
override void UpdateVisuals()
Definition Watchtower.c:44
override bool PerformRoofCheckForBase(string partName, PlayerBase player, out bool result)
Definition Watchtower.c:133
override void OnPartBuiltServer(notnull Man player, string part_name, int action_id)
Definition Watchtower.c:356
override void SetActions()
Definition Watchtower.c:497
override bool CheckSlotVerticalDistance(int slot_id, PlayerBase player)
Definition Watchtower.c:267
override bool IsFacingCamera(string selection)
Definition Watchtower.c:422
override bool IsFacingPlayer(PlayerBase player, string selection)
Definition Watchtower.c:379
override void AfterStoreLoad()
Definition Watchtower.c:349
override int GetMeleeTargetType()
Definition Watchtower.c:26
override bool HasProperDistance(string selection, PlayerBase player)
Definition Watchtower.c:484
override void OnPartDestroyedServer(Man player, string part_name, int action_id, bool destroyed_by_connected_part=false)
Definition Watchtower.c:370
override bool CanReceiveAttachment(EntityAI attachment, int slotId)
Definition Watchtower.c:90
override bool CanBeRepairedToPristine()
Definition Watchtower.c:128
static const int MAX_WATCHTOWER_FLOORS
Definition Watchtower.c:14
override bool CheckMemoryPointVerticalDistance(float max_dist, string selection, PlayerBase player)
Definition Watchtower.c:313
static const string BASE_ROOF_NAME
Definition Watchtower.c:13
override void OnPartDismantledServer(notnull Man player, string part_name, int action_id)
Definition Watchtower.c:363
static bool GetDisablePerformRoofCheck()
provides access to slot configuration
static proto native owned string GetSlotName(int id)
converts slot_id to string
static proto bool GetSelectionForSlotId(int slot_Id, out string selection)
Definition EnMath.c:7
static float Dot(vector v1, vector v2)
Returns Dot product of vector v1 and vector v2.
Definition EnConvert.c:271
static proto native float Distance(vector v1, vector v2)
Returns the distance between tips of two 3D vectors.
proto native CGame GetGame()
static proto bool GetBool(int id, bool reverse=false)
Get value as bool from the given script id.
static proto float AbsFloat(float f)
Returns absolute value.
bool Contains(string sample)
Returns true if sample is substring of string.
Definition EnString.c:286