Dayz Explorer 1.28.160049
Loading...
Searching...
No Matches
plantbase.c
Go to the documentation of this file.
9
10class PlantBase extends ItemBase
11{
12 private float m_SprayUsage; // How much spray is needed to stop infestation of plant
13
14 private float m_InfestationChance;
15
16 private int m_GrowthStagesCount;
17 private int m_CropsCount;
18 private bool m_HasCrops;
19 private string m_CropsType;
20 private float m_PlantMaterialMultiplier;
21
22 private int m_PlantStateIndex;
23 private float m_CurrentPlantMaterialQuantity;
25
26 private bool m_IsInfested;
27 private float m_SprayQuantity;
28 bool m_MarkForDeletion = false;
29
30 int m_DeleteDryPlantTime; // For how long in seconds can an unwatered plant exist before it disappears
31 int m_SpoiledRemoveTime; // For how long in seconds a spoiled plant will exist
32 int m_FullMaturityTime; // How much time needs plant to be full grown in seconds
33 int m_SpoilAfterFullMaturityTime; // How long in seconds it takes for plant to be spoiled after it is full grown
34 float m_StateChangeTime; // For how long in seconds will plant stay in one state before its going to next state
35
36 protected ref Timer m_TimeTicker;
37 protected float m_TimeTracker;
38
39 private GardenBase m_GardenBase = NULL;
40 private ref Slot m_Slot = NULL;
41
42 private PluginHorticulture m_ModuleHorticulture;
43
44 private const float SPOIL_AFTER_MATURITY_TIME = 14400.0; //The time it takes for a fully grown plant to spoil, in seconds (4 hours)
45 private const int TICK_FREQUENCY = 1; // seconds
46
47 // debug
48 static int m_DebugFullMaturityTime;
49 static int m_DebugSpoilTime;
50 static int m_DebugSpoilRemoveTime;
51 static int m_DebugDeleteDryTime;
52 static float m_DebugTickSpeedMultiplier = 1;
53
54 void PlantBase()
55 {
56 m_ModuleHorticulture = PluginHorticulture.Cast( GetPlugin( PluginHorticulture ) );
57
58 m_SprayUsage = 5;
59 m_DeleteDryPlantTime = (60 * 10) + Math.RandomInt(0, 60 * 2);
60 m_SpoiledRemoveTime = (60 * 20) + Math.RandomInt(0, 60 * 5);
61
62 string plant_type = this.GetType();
63 m_GrowthStagesCount = GetGame().ConfigGetInt( "cfgVehicles " + plant_type + " Horticulture GrowthStagesCount" );
64 m_CropsCount = GetGame().ConfigGetInt( "cfgVehicles " + plant_type + " Horticulture CropsCount" );
65 GetGame().ConfigGetText( "cfgVehicles " + plant_type + " Horticulture CropsType", m_CropsType );
66
67 if (m_GrowthStagesCount == 0)
68 m_GrowthStagesCount = 1;
69
70 m_InfestationChance = 0.2 / m_GrowthStagesCount; //Must be between 0 and 1
71
72 m_PlantStateIndex = -1;
73 m_CurrentPlantMaterialQuantity = 0;
74 m_IsInfested = false;
75 m_SprayQuantity = 0.0;
76 m_HasCrops = true;
77
78 SetTakeable( false );
79
80 RegisterNetSyncVariableBool("m_HasCrops");
81 RegisterNetSyncVariableInt("m_PlantState");
82 RegisterNetSyncVariableInt("m_PlantStateIndex");
83
84 if (GetGame().IsServer())
85 {
87 m_TimeTicker.Run(TICK_FREQUENCY, this, "Tick", NULL, true);
88 }
89 }
90
91 void ~PlantBase()
92 {
93 if (m_TimeTicker)
94 m_TimeTicker.Stop();
95
96 if (!m_MarkForDeletion && !IsPendingDeletion())
97 {
98 DestroyPlant();
99 }
100 }
101
102 void Init( GardenBase garden_base, float fertility, float harvesting_efficiency, float water )
103 {
104 m_GardenBase = garden_base;
105
106 if (m_DebugFullMaturityTime != 0)
107 m_FullMaturityTime = m_DebugFullMaturityTime;
108 else
109 m_FullMaturityTime += Math.RandomInt(-60,180);
110
111 if (m_DebugSpoilTime != 0)
112 m_SpoilAfterFullMaturityTime = m_DebugSpoilTime;
113 else
114 m_SpoilAfterFullMaturityTime = SPOIL_AFTER_MATURITY_TIME;
115
116 if (m_DebugSpoilRemoveTime != 0)
117 m_SpoiledRemoveTime = m_DebugSpoilRemoveTime;
118
119 if (m_DebugDeleteDryTime != 0)
120 m_DeleteDryPlantTime = m_DebugDeleteDryTime;
121
122 m_StateChangeTime = m_FullMaturityTime / (m_GrowthStagesCount - 2);
123
124 float count = m_CropsCount * fertility * harvesting_efficiency;
125 m_CropsCount = (int)Math.Ceil( count );
126
127 m_PlantMaterialMultiplier = 0.1 * harvesting_efficiency;
128
129 float rain_intensity = GetGame().GetWeather().GetRain().GetActual();
130
131 if (m_PlantState < EPlantState.MATURE && !NeedsWater())
132 {
133 SetPlantState(EPlantState.GROWING);
134 GrowthTimerTick(); // first tick happens straight away
135 }
136
137 if (rain_intensity <= 0.0)
138 {
139 if (NeedsWater())
140 SetPlantState(EPlantState.PAUSED);
141 }
142 }
143
144 void Tick()
145 {
146 m_TimeTracker += m_TimeTicker.GetDuration() * m_DebugTickSpeedMultiplier;
147
148 switch (m_PlantState)
149 {
150 case (EPlantState.GROWING):
151 if (m_TimeTracker >= m_StateChangeTime)
152 GrowthTimerTick();
153
154 break;
155
156 case (EPlantState.MATURE):
157 if (m_TimeTracker >= m_SpoilAfterFullMaturityTime)
158 SetSpoiled();
159
160 break;
161
162 case (EPlantState.SPOILED):
163 if (m_TimeTracker >= m_SpoiledRemoveTime)
164 RemoveSlot();
165
166 break;
167
168 case (EPlantState.DRY):
169 if (m_TimeTracker >= m_DeleteDryPlantTime)
170 RemoveSlot();
171
172 break;
173 }
174
175 }
176
177 override bool OnStoreLoad( ParamsReadContext ctx, int version )
178 {
179 if ( !super.OnStoreLoad( ctx, version ) )
180 return false;
181
182 GardenBase garden = GardenBase.Cast( GetHierarchyParent() );
183
184 int slot_index = -1;
185 if (!ctx.Read(slot_index))
186 return false;
187
188 Slot slot = garden.GetSlotByIndex(slot_index);
189
190 SetSlot(slot);
191
192 if ( !OnStoreLoadCustom( ctx, version ) )
193 return false;
194
195 return true;
196 }
197
198 override void OnStoreSave( ParamsWriteContext ctx )
199 {
200 super.OnStoreSave( ctx );
201
202 Slot slot = GetSlot();
203
204 if (slot)
205 {
206 int slot_index = slot.GetSlotIndex();
207 slot.SetPlant(this); // hack
208
209 ctx.Write( slot_index );
210
211 OnStoreSaveCustom( ctx );
212 }
213 else
214 {
215 ErrorEx("[Warning] A plant existed without a garden. Therefore it was deleted from the world to prevent issues! Position: " + GetPosition(), ErrorExSeverity.INFO);
216 GetGame().ObjectDelete(this); // Plants that exist without a garden must be deleted. Otherwise they might cause problems.
217 }
218 }
219
220 string GetCropsType()
221 {
222 return m_CropsType;
223 }
224
225 bool OnStoreLoadCustom(ParamsReadContext ctx, int version)
226 {
227 if (!ctx.Read(m_SprayUsage))
228 return false;
229
230 if (!ctx.Read(m_DeleteDryPlantTime))
231 return false;
232
233 if (!ctx.Read(m_SpoiledRemoveTime))
234 return false;
235
236 if (!ctx.Read(m_FullMaturityTime))
237 return false;
238
239 if (!ctx.Read(m_SpoilAfterFullMaturityTime))
240 return false;
241
242 if (!ctx.Read(m_StateChangeTime))
243 return false;
244
245 if (!ctx.Read(m_InfestationChance))
246 return false;
247
248 if (!ctx.Read(m_GrowthStagesCount))
249 return false;
250
251 if (!ctx.Read(m_CropsCount))
252 return false;
253
254 if (!ctx.Read(m_CropsType))
255 return false;
256
257 if (!ctx.Read(m_PlantMaterialMultiplier))
258 return false;
259
260 if (!ctx.Read(m_PlantState))
261 return false;
262
263 if (!ctx.Read(m_PlantStateIndex))
264 return false;
265
266 if (!ctx.Read(m_CurrentPlantMaterialQuantity))
267 return false;
268
269 if (!ctx.Read(m_IsInfested))
270 return false;
271
272 if (!ctx.Read(m_SprayQuantity))
273 return false;
274
275 bool loadBool; // deprec
276 if (!ctx.Read(loadBool))
277 return false;
278
279 float loadFloat = 0.0;
280 if (!ctx.Read(loadFloat)) // deprec
281 return false;
282
283 loadFloat = 0.0;
284 if (ctx.Read(loadFloat))
285 {
286 if (loadFloat > 0.0)
287 m_TimeTracker = loadFloat; // spoil
288 }
289 else
290 {
291 return false;
292 }
293
294 loadFloat = 0.0;
295 if (ctx.Read(loadFloat))
296 {
297 if (loadFloat > 0.0)
298 m_TimeTracker = loadFloat; // spoil delete
299 }
300 else
301 {
302 return false;
303 }
304
305 loadFloat = 0.0;
306 if (ctx.Read(loadFloat))
307 {
308 if ( loadFloat > 0.0 )
309 m_TimeTracker = loadFloat; // dry delete
310 }
311 else
312 {
313 return false;
314 }
315
316 if (m_StateChangeTime != (m_FullMaturityTime / (m_GrowthStagesCount - 2)))
317 {
318 m_StateChangeTime = m_FullMaturityTime / (m_GrowthStagesCount - 2);
319 ErrorEx("[Warning] A plant loaded from storage had a corrupted state change time. Time was now adjusted! Position: " + GetPosition(), ErrorExSeverity.INFO);
320 }
321
322 if (version >= 142)
323 {
324 if (!ctx.Read(m_HasCrops))
325 return false;
326 }
327
328 UpdatePlant();
329 return true;
330 }
331
332 void OnStoreSaveCustom( ParamsWriteContext ctx )
333 {
334 ctx.Write(m_SprayUsage);
335 ctx.Write(m_DeleteDryPlantTime);
336 ctx.Write(m_SpoiledRemoveTime);
337 ctx.Write(m_FullMaturityTime);
338 ctx.Write(m_SpoilAfterFullMaturityTime);
339 ctx.Write(m_StateChangeTime);
340 ctx.Write(m_InfestationChance);
341 ctx.Write(m_GrowthStagesCount);
342 ctx.Write(m_CropsCount);
343 ctx.Write(m_CropsType);
344 ctx.Write(m_PlantMaterialMultiplier);
345 ctx.Write(m_PlantState);
346 ctx.Write(m_PlantStateIndex);
347 ctx.Write(m_CurrentPlantMaterialQuantity);
348 ctx.Write(m_IsInfested);
349 ctx.Write(m_SprayQuantity);
350
351 bool saveBool = false; // deprec
352 ctx.Write( saveBool );
353
354 float saveFloat = 0.0; // deprec
355 ctx.Write( saveFloat );
356
357 saveFloat = 0.0;
358 if (m_PlantState == EPlantState.MATURE)
359 {
360 saveFloat = m_TimeTracker;
361 }
362 ctx.Write( saveFloat );
363
364 saveFloat = 0.0;
365 if (m_PlantState == EPlantState.SPOILED)
366 {
367 saveFloat = m_TimeTracker;
368 }
369 ctx.Write( saveFloat );
370
371 saveFloat = 0.0;
372 if (m_PlantState == EPlantState.DRY)
373 {
374 saveFloat = m_TimeTracker;
375 }
376 ctx.Write( saveFloat );
377
378 ctx.Write(m_HasCrops);
379 }
380
381 void PrintValues()
382 {
383 Print("PRINT ALL VALUES OF PLANT...");
384 Print(this);
385
386 Print(m_GrowthStagesCount);
387 Print(m_HasCrops);
388 Print(typename.EnumToString(EPlantState, m_PlantState));
389 Print(m_PlantStateIndex);
390 Print(m_CurrentPlantMaterialQuantity);
391 Print(m_IsInfested);
392 Print(m_SprayQuantity);
393 Print(m_Slot);
394 Print(m_GardenBase);
395 Print(m_StateChangeTime);
396 Print(m_FullMaturityTime);
397 Print(m_SpoilAfterFullMaturityTime);
399 Print("----------------------------------------------------------");
400 }
401
402 override bool CanPutInCargo( EntityAI parent )
403 {
404 return super.CanPutInCargo(parent);
405 }
406
407 override bool CanPutIntoHands( EntityAI parent )
408 {
409 return super.CanPutIntoHands(parent);
410 }
411
412 override bool CanRemoveFromHands( EntityAI parent )
413 {
414 return false;
415 }
416
417 void ChangeInfestation( bool is_infested )
418 {
419 m_IsInfested = is_infested;
420
421 string plant_type = GetType();
422 PlantMaterialHealth material = m_ModuleHorticulture.GetPlantMaterial( plant_type );
423
424 if ( m_IsInfested )
425 {
426 if ( material.m_InfestedTex != "" )
427 {
428 SetObjectTexture( 0, material.m_InfestedTex );
429 }
430 if ( material.m_InfestedMat != "" )
431 {
432 SetObjectMaterial( 0, material.m_InfestedMat );
433 }
434 }
435 else
436 {
437 if ( material.m_HealthyTex != "" )
438 {
439 SetObjectTexture( 0, material.m_HealthyTex );
440 }
441 if ( material.m_HealthyMat != "" )
442 {
443 SetObjectMaterial( 0, material.m_HealthyMat );
444 }
445 }
446 }
447
448 void UpdatePlant()
449 {
450 if ( m_PlantStateIndex > 0 )
451 {
452 string plant_state_index = m_PlantStateIndex.ToStringLen(2);
453 string prev_plant_state_index = ( m_PlantStateIndex - 1 ).ToStringLen( 2 );
454
455 // HIDING PREVIOUS PLANT STATE AND SHOWING THE CURRENT ONE
456 ShowSelection( "plantStage_" + plant_state_index ); // SHOW!
457 HideSelection( "plantStage_" + prev_plant_state_index ); // HIDE!
458
459 // HIDING PREVIOUS CROPS STATE AND SHOWING THE CURRENT ONE
460
461 if ( HasCrops() )
462 {
463 ShowSelection( "plantStage_" + plant_state_index + "_crops" ); // SHOW!
464 HideSelection( "plantStage_" + prev_plant_state_index + "_crops" ); // HIDE!
465 }
466 else
467 {
468 HideSelection( "plantStage_" + plant_state_index + "_crops" ); // HIDE!
469 HideSelection( "plantStage_" + prev_plant_state_index + "_crops" ); // HIDE!
470 }
471
472 // HIDING PREVIOUS SHADOW STATE AND SHOWING THE CURRENT ONE
473 ShowSelection( "plantStage_" + plant_state_index + "_shadow" ); // SHOW!
474 HideSelection( "plantStage_" + prev_plant_state_index + "_shadow" ); // HIDE!
475 }
476
477 float float_plant_state_index = (float)m_PlantStateIndex;
478 m_CurrentPlantMaterialQuantity = m_PlantMaterialMultiplier * float_plant_state_index;
479 }
480
481 void GrowthTimerTick()
482 {
483 m_TimeTracker = 0;
484
485 if ( m_PlantStateIndex < m_GrowthStagesCount - 2 )
486 {
487 m_PlantStateIndex++;
488 UpdatePlant();
489 SetSynchDirty();
490
491 float infestation_rnd = Math.RandomFloat01();
492 if ( m_InfestationChance > infestation_rnd )
493 ChangeInfestation(true);
494
495 if ( m_PlantStateIndex == m_GrowthStagesCount - 2 )
496 {
497 if (m_IsInfested)
498 SetDry();
499 else
500 SetPlantState(EPlantState.MATURE);
501 }
502 }
503 }
504
505 void SetSpoiled()
506 {
507 if (m_PlantState != EPlantState.SPOILED)
508 {
509 m_PlantStateIndex++;
510 UpdatePlant();
511 SetPlantState(EPlantState.SPOILED);
512 }
513 }
514
515 void SetDry()
516 {
517 if (m_PlantState != EPlantState.DRY)
518 {
519 m_PlantStateIndex++;
520 UpdatePlant();
521 SetPlantState(EPlantState.DRY);
522 }
523 }
524
525 //NEW METHOD FOR PLANT SPRAYING
526 void SprayPlant( float consumed_quantity )
527 {
528 //Rework this to have something smooth
529 m_SprayQuantity += consumed_quantity;
530
531 if (m_SprayQuantity >= m_SprayUsage)
532 {
533 m_IsInfested = false;
534 m_InfestationChance = 0;
535
536 ChangeInfestation( false );
537 UpdatePlant();
538 }
539 }
540
541 void RemovePlantEx( vector pos )
542 {
543 if ( GetGame() && GetGame().IsServer() )
544 {
545 UnlockFromParent();
546
547 if ( m_CurrentPlantMaterialQuantity > 0.0 )
548 {
549 ItemBase item = ItemBase.Cast( GetGame().CreateObjectEx( "PlantMaterial", pos, ECE_PLACE_ON_SURFACE ) );
550 item.SetQuantity( m_CurrentPlantMaterialQuantity * 1000.0 );
551 }
552
553 RemoveSlot();
554 }
555 }
556
557 void DestroyPlant()
558 {
559 if ( GetGame() && GetGame().IsServer() )
560 {
561 UnlockFromParent();
562
563 RemoveSlot();
564 }
565 }
566
567 void Harvest( PlayerBase player )
568 {
569 if (IsHarvestable())
570 {
571 for ( int i = 0; i < m_CropsCount; i++ )
572 {
573 vector pos = player.GetPosition();
574 ItemBase item = ItemBase.Cast( GetGame().CreateObjectEx( m_CropsType, pos, ECE_PLACE_ON_SURFACE ) );
575 item.SetQuantity( item.GetQuantityMax() );
576 }
577 }
578
579 m_HasCrops = false;
580
581 SetSynchDirty();
582
583 UpdatePlant();
584 m_GardenBase.SyncSlots();
585 }
586
587 void SetPlantState(int state)
588 {
589 m_PlantState = state;
590 m_TimeTracker = 0;
591 SetSynchDirty();
592 }
593
594 EPlantState GetPlantState()
595 {
596 return m_PlantState;
597 }
598
599 int GetPlantStateIndex()
600 {
601 return m_PlantStateIndex;
602 }
603
604 float GetWater()
605 {
606 if ( GetSlot() )
607 return GetSlot().GetWater();
608
609 return 0;
610 }
611
612 float GetWaterMax()
613 {
614 if ( GetSlot() )
615 return GetSlot().GetWaterUsage();
616
617 return 0;
618 }
619
620 bool NeedsWater()
621 {
622 Slot slotPlant = m_Slot;
623
624 if ( m_PlantState == EPlantState.PAUSED && slotPlant && slotPlant.GetWater() < slotPlant.GetWaterUsage() )
625 return true;
626
627 return false;
628 }
629
630 float GetSprayQuantity()
631 {
632 return m_SprayQuantity;
633 }
634
635 float GetSprayUsage()
636 {
637 return m_SprayUsage;
638 }
639
640 void RemoveSlot()
641 {
642 GardenBase garden = GardenBase.Cast( GetHierarchyParent() );
643
644 if ( garden )
645 garden.RemoveSlotPlant( this );
646 }
647
648 void SetSlot(Slot slot)
649 {
650 if ( slot )
651 {
652 m_Slot = slot;
653 }
654 }
655
656 Slot GetSlot()
657 {
658 return m_Slot;
659 }
660
661 void SetGarden(GardenBase gardenBase)
662 {
663 m_GardenBase = gardenBase;
664 }
665
666 GardenBase GetGarden()
667 {
668 return m_GardenBase;
669 }
670
671 bool IsSprayable()
672 {
673 if (m_PlantState == EPlantState.GROWING && m_SprayQuantity < m_SprayUsage)
674 return true;
675
676 return false;
677 }
678
679 bool IsHarvestable()
680 {
681 if (m_PlantState == EPlantState.MATURE && m_HasCrops)
682 return true;
683
684 return false;
685 }
686
687 bool HasCrops()
688 {
689 return m_HasCrops;
690 }
691
692 override void SetActions()
693 {
694 super.SetActions();
695
698 }
699
700 void DebugSetTimes(int maturity, int spoil, int spoilRemove, int dryDelete)
701 {
702 if (maturity != 0)
703 {
704 m_FullMaturityTime = maturity;
705 m_StateChangeTime = m_FullMaturityTime / (m_GrowthStagesCount - 2);
706 }
707
708 if (spoil != 0)
709 m_SpoilAfterFullMaturityTime = spoil;
710
711 if (spoilRemove != 0)
712 m_SpoiledRemoveTime = spoilRemove;
713
714 if (dryDelete != 0)
715 m_DeleteDryPlantTime = dryDelete;
716 }
717
718 static void DebugSetGlobalTimes(int maturity, int spoil, int spoilRemove, int dryDelete)
719 {
720 m_DebugFullMaturityTime = maturity;
721 m_DebugSpoilTime = spoil;
722 m_DebugSpoilRemoveTime = spoilRemove;
723 m_DebugDeleteDryTime = dryDelete;
724 }
725
726 static void DebugSetTickSpeedMultiplier(float multiplier)
727 {
728 m_DebugTickSpeedMultiplier = multiplier;
729 }
730
731 // DEPRECATED
732 static const int STATE_DRY = 0;
733 static const int STATE_GROWING = 1;
734 static const int STATE_MATURE = 2;
735 static const int STATE_SPOILED = 3;
736
737 ref Timer m_SpoiledRemoveTimer;
738 ref Timer m_DeleteDryPlantTimer;
739 ref Timer m_SpoilAfterFullMaturityTimer;
740 ref Timer m_GrowthTimer;
741 ref Timer m_InfestationTimer;
742
743 void DeleteDryPlantTick();
744 void SpoiledRemoveTimerTick();
745 void InfestationTimerTick();
746 void CheckWater();
747 bool IsMature();
748 bool IsSpoiled();
749 bool IsDry();
750 bool IsGrowing();
751 bool NeedsSpraying();
752 void RemovePlant();
753 string StopInfestation( float consumed_quantity )
754 {
755 return "";
756 }
757}
Param3 int
eBleedingSourceType GetType()
void AddAction(typename actionName)
void SetActions()
const int ECE_PLACE_ON_SURFACE
proto native Weather GetWeather()
Returns weather controller object.
Definition enmath.c:7
Serialization general interface. Serializer API works with:
Definition serializer.c:56
override void Tick()
override Widget Init()
Definition dayzgame.c:127
string ToStringLen(int len)
Integer to string with fixed length, padded with zeroes.
Definition enconvert.c:59
override bool CanPutInCargo(EntityAI parent)
override bool CanPutIntoHands(EntityAI parent)
override bool CanRemoveFromHands(EntityAI parent)
proto native CGame GetGame()
ErrorExSeverity
Definition endebug.c:62
proto void Print(void var)
Prints content of variable to console/log.
enum ShapeType ErrorEx
bool IsPendingDeletion()
Get whether the Effect is queued up for being cleaned up.
Definition effect.c:260
class JsonUndergroundAreaTriggerData GetPosition
const int CALL_CATEGORY_SYSTEM
Definition tools.c:8
override void SetTakeable(bool pState)
Definition itembase.c:9184
void OnStoreSave(ParamsWriteContext ctx)
bool OnStoreLoad(ParamsReadContext ctx, int version)
float m_TimeTracker
Definition plantbase.c:37
ref Timer m_TimeTicker
Definition plantbase.c:36
enum EPlantState m_SprayUsage
EPlantState m_PlantState
Definition plantbase.c:24
EPlantState
Definition plantbase.c:2
@ MATURE
Definition plantbase.c:5
@ SPOILED
Definition plantbase.c:6
@ DRY
Definition plantbase.c:7
@ GROWING
Definition plantbase.c:4
@ PAUSED
Definition plantbase.c:3
PluginBase GetPlugin(typename plugin_type)