-
-
Notifications
You must be signed in to change notification settings - Fork 588
Expand file tree
/
Copy pathConstants.cs
More file actions
2365 lines (1804 loc) · 97.2 KB
/
Constants.cs
File metadata and controls
2365 lines (1804 loc) · 97.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using Godot;
using LauncherThriveShared;
using Newtonsoft.Json;
/// <summary>
/// Holds some constants that must be kept constant everywhere in the game. Many of these can be tweaked to adjust
/// game balance.
/// </summary>
public static class Constants
{
/// <summary>
/// Used to prevent lag causing massive simulation instability spikes (due to resource consumption etc. scaling
/// but storage not scaling)
/// </summary>
public const float SIMULATION_MAX_DELTA_TIME = 0.2f;
/// <summary>
/// Controls the number of threads used by the entity systems. The number of cells is divided by this,
/// and that is the max number of threads.
/// </summary>
public const int SIMULATION_CELLS_PER_THREAD_ESTIMATE = 25;
public const float SIMULATION_REQUIRED_FAST_MODE_SUCCESS_RATE = 0.45f;
// The following variables define the number of entities each thread running a system of that category needs to be
// able to process for threading to be used at all. For example, if there are 40 entities and 4 threads to be used
// and a system specifies 10 entities per thread, that system will run multithreaded (4 * 10 {40} <= 40).
// But if there was a system that wanted at least 15 entities per thread, that would run purely *single threaded*
// (4 * 15 {60} <= 40)
public const int SYSTEM_LOW_ENTITIES_PER_THREAD = 8;
public const int SYSTEM_NORMAL_ENTITIES_PER_THREAD = 12;
public const int SYSTEM_HIGHER_ENTITIES_PER_THREAD = 18;
public const int SYSTEM_HIGH_ENTITIES_PER_THREAD = 24;
public const int SYSTEM_EXTREME_ENTITIES_PER_THREAD = 40;
/// <summary>
/// Makes sure that at least this many task threads are left idle when creating membrane generation background
/// tasks.
/// </summary>
public const int MEMBRANE_TASKS_LEAVE_EMPTY_THREADS = 2;
/// <summary>
/// Default length in seconds for an in-game day. If this is changed, the placeholder values in
/// NewGameSettings.tscn should also be changed.
/// </summary>
public const int DEFAULT_DAY_LENGTH = 180;
/// <summary>
/// How long the player stays dead before respawning (this is after the animation of dying ends)
/// </summary>
public const float PLAYER_RESPAWN_TIME = 2.0f;
/// <summary>
/// The player is guaranteed to die within this time when using the suicide button. This exists to prevent total
/// softlocks.
/// </summary>
public const float MAX_PLAYER_DYING_TIME = 10;
/// <summary>
/// How long the initial compounds should last (in seconds)
/// </summary>
public const float INITIAL_COMPOUND_TIME = 40.0f;
/// <summary>
/// Needed to get the cell positions when creating the actual colonies to line up where they should.
/// TODO: figure out a better approach to multicellular cell positioning than this to avoid gaps (or maybe a post
/// process step when membranes are ready to pull cells closer to close up any gaps?)
/// </summary>
/// <remarks>
/// <para>
/// Lowering this makes up/down direction cells closer to touching, but increases overlap on horizontally next
/// to each other.
/// </para>
/// </remarks>
public const float MULTICELLULAR_CELL_DISTANCE_MULTIPLIER = 1.55f;
public const float MULTICELLULAR_INITIAL_COMPOUND_MULTIPLIER = 1.5f;
public const int FULL_INITIAL_GLUCOSE_SMALL_SIZE_LIMIT = 3;
/// <summary>
/// The maximum duration the player is shown being ingested before they are auto-respawned.
/// </summary>
public const float PLAYER_ENGULFED_DEATH_DELAY_MAX = 10.0f;
// Variance in the player position when respawning
public const float MIN_SPAWN_DISTANCE = -5000.0f;
public const float MAX_SPAWN_DISTANCE = 5000.0f;
/// <summary>
/// Size of "chunks" used for spawning entities
/// </summary>
public const float SPAWN_SECTOR_SIZE = 120.0f;
public const float MIN_DISTANCE_FROM_PLAYER_FOR_SPAWN = SPAWN_SECTOR_SIZE - 10;
/// <summary>
/// Used to reduce how commonly the player species spawns to make it more likely for the player to encounter
/// other species.
/// </summary>
public const float PLAYER_SPECIES_SPAWN_MULTIPLIER = 0.5f;
/// <summary>
/// Smaller spawn penalty to make binding agents easier to use with better player species spawn rates.
/// </summary>
public const float PLAYER_SPECIES_SPAWN_MULTIPLIER_BINDING_AGENTS = 0.7f;
/// <summary>
/// Cells farther than this are forced to move towards the player to get on screen to give better activity
/// from our limited entity count. Lower values let farther away cells to just chill without having to move.
/// </summary>
public const float ON_STAGE_THRESHOLD_AROUND_PLAYER = 0.71f;
/// <summary>
/// Sets much randomness is added on each axis (X and Z) for a cell's target to move to the player position to
/// get "on stage"
/// Larger values add more randomness to cells moving towards the player.
/// </summary>
public const float ON_STAGE_DESTINATION_RANDOMNESS = 20;
/// <summary>
/// Scale factor for density of compound cloud spawns
/// </summary>
public const int CLOUD_SPAWN_DENSITY_SCALE_FACTOR = 10000;
/// <summary>
/// Scale factor for the amount of compound in each spawned cloud
/// </summary>
public const float CLOUD_SPAWN_AMOUNT_SCALE_FACTOR = 0.75f;
/// <summary>
/// Threshold under which entities start to spawn around the player
/// The value is in the range 0-1 and is the fraction of the maximum
/// allowed entities.
/// </summary>
public const float ENTITY_SPAWNING_AROUND_PLAYER_THRESHOLD = 0.8f;
/// <summary>
/// Scale factor for how dense microbes spawn (also affected by their populations).
/// </summary>
/// <remarks>
/// <para>
/// Due to an earlier problem, old species spawners were never cleared, so they accumulated a lot.
/// This multiplier has now been increased quite a bit to try to make the lower number of species spawners
/// result in the same level of microbe spawning.
/// </para>
/// </remarks>
public const float MICROBE_SPAWN_DENSITY_SCALE_FACTOR = 0.022f;
/// <summary>
/// Along with <see cref="MICROBE_SPAWN_DENSITY_SCALE_FACTOR"/> affects spawn density of microbes.
/// The lower this multiplier is set, the more even species with different populations are spawned.
/// </summary>
public const float MICROBE_SPAWN_DENSITY_POPULATION_MULTIPLIER = 1 / 25.0f;
/// <summary>
/// The (default) size of the hexagons, used in calculations. Don't change this.
/// </summary>
public const float DEFAULT_HEX_SIZE = 0.75f;
/// <summary>
/// Don't change this, so much stuff will break
/// </summary>
public const int CLOUDS_IN_ONE = 4;
public const int CLOUD_SQUARES_PER_SIDE = 3;
public const int CLOUD_EDGE_WIDTH = 2;
// NOTE: these 4 constants need to match what is set up in CompoundCloudPlane.tscn
public const int CLOUD_WIDTH = 300;
public const int CLOUD_X_EXTENT = CLOUD_WIDTH * 2;
public const int CLOUD_HEIGHT = 300;
// This is cloud local Y, not world Y
public const int CLOUD_Y_EXTENT = CLOUD_HEIGHT * 2;
public const float CLOUD_Y_COORDINATE = 0;
public const float CLOUD_DIFFUSION_RATE = 0.007f;
// Should be the same as its counterpart in shaders/CompoundCloudPlane.shader
public const float CLOUD_MAX_INTENSITY_SHOWN = 1000;
public const float CLOUD_CHEAT_DENSITY = 16000.0f;
// public const float TERRAIN_GRID_SIZE = 200;
public const float TERRAIN_GRID_SIZE_X = 300;
public const float TERRAIN_GRID_SIZE_Z = 275;
// public const float TERRAIN_GRID_SIZE_INV = 1 / TERRAIN_GRID_SIZE;
public const float TERRAIN_GRID_SIZE_INV_X = 1 / TERRAIN_GRID_SIZE_X;
public const float TERRAIN_GRID_SIZE_INV_Z = 1 / TERRAIN_GRID_SIZE_Z;
public const float TERRAIN_EDGE_PROTECTION_SIZE = 1;
/// <summary>
/// Adds randomness to microbe terrain height so that there's no z-fighting if terrain ends up overlapping
/// </summary>
public const float TERRAIN_HEIGHT_RANDOMNESS = 0.001f;
/// <summary>
/// In how big the radius (in terms of grid cells) around the player terrain is spawned in.
/// If too low, then pop in is visible and the spawn system can spawn stuff in that then gets covered
/// by the terrain.
/// </summary>
public const int TERRAIN_SPAWN_AREA_NUMBER = 1;
public const int TERRAIN_VENT_SEGMENTS = 6;
public const int TERRAIN_VENT_RINGS_MAX = 5;
public const int TERRAIN_VENT_RINGS_MIN = 2;
public const int TERRAIN_SECOND_VENT_RINGS_MIN_THRESHOLD = 3;
public const float TERRAIN_SECOND_VENT_CHANCE = 0.4f;
public const int TERRAIN_VENT_OVERLAP_MARGIN = 2;
public const int TERRAIN_VENT_RING_HEIGHT_REDUCTION = 10;
public const int TERRAIN_VENT_OUTER_RING_HEIGHT = -27;
public const int MEMBRANE_RESOLUTION = 10;
public const int MEMBRANE_VERTICAL_RESOLUTION = 7;
public const float MEMBRANE_HEIGHT_MULTIPLIER = 1.0f;
public const float MEMBRANE_SMOOTHING_POWER = 3.0f;
public const float MEMBRANE_SIDE_ROUNDING = 20.0f;
public const float MEMBRANE_ROOM_FOR_ORGANELLES = 1.9f;
public const float MEMBRANE_NUMBER_OF_WAVES = 9.0f;
public const float MEMBRANE_WAVE_HEIGHT_DEPENDENCE_ON_SIZE = 0.3f;
public const float MEMBRANE_WAVE_HEIGHT_MULTIPLIER = 0.025f;
public const float MEMBRANE_WAVE_HEIGHT_MULTIPLIER_CELL_WALL = 0.015f;
public const float MEMBRANE_ENGULF_ANIMATION_DISTANCE = 1.25f;
/// <summary>
/// BASE MOVEMENT ATP cost. Cancels out a little bit more then one cytoplasm's glycolysis
/// </summary>
/// <remarks>
/// <para>
/// this is applied *per* hex
/// </para>
/// </remarks>
public const float BASE_MOVEMENT_ATP_COST = 1.0f;
public const float BASE_MOVEMENT_FORCE = 900.0f;
public const float MAX_STRAIN_PER_ENTITY = 400.0f;
public const float MIN_STRAIN_SPRINT_REGAIN = 200.0f;
public const float PASSIVE_STRAIN_DECREASE_PER_SECOND = 30.0f;
public const float PASSIVE_STRAIN_DECREASE_PRE_COOLDOWN_MULTIPLIER = 0.3f;
/// <summary>
/// This is multiplied by the strain fraction to get the ATP usage multiplier
/// </summary>
public const float STRAIN_TO_ATP_USAGE_COEFFICIENT = 1.5f;
/// <summary>
/// How much strain does not affect ATP usage at first
/// </summary>
public const float CANCELED_STRAIN = 10.0f;
public const float STRAIN_DECREASE_COOLDOWN_SECONDS = 0.5f;
public const float SPRINTING_STRAIN_INCREASE_PER_SECOND = 72.0f;
public const float SPRINTING_STRAIN_INCREASE_PER_HEX = 0.15f;
public const float SPRINTING_FORCE_MULTIPLIER = 1.8f;
public const float FLAGELLA_ENERGY_COST = 6.0f;
public const float FLAGELLA_BASE_FORCE = 20.0f;
/// <summary>
/// TODO: this needs to be dynamically calculated: https://github.com/Revolutionary-Games/Thrive/issues/5591
/// </summary>
public const float FLAGELLA_SPEED_BONUS_DISPLAY = 0.7f;
public const float FLAGELLA_MAX_UPGRADE_LENGHT = 3;
public const float FLAGELLA_MIN_UPGRADE_LENGHT = -1;
public const float FLAGELLA_MAX_UPGRADE_FORCE = 15.0f;
public const float FLAGELLA_MAX_UPGRADE_ATP_USAGE = 4.0f;
public const float FLAGELLA_MAX_UPGRADE_VISUAL_LENGTH = 0.40f;
public const float FLAGELLA_MIN_UPGRADE_VISUAL_LENGTH = 0.80f;
/// <summary>
/// As eukaryotes are immediately 50% larger, they get a movement force increase to offset that
/// </summary>
public const float EUKARYOTIC_MOVEMENT_FORCE_MULTIPLIER = 2.5f;
/// <summary>
/// Amount of extra base movement given per hex. Only applies between
/// <see cref="BASE_MOVEMENT_EXTRA_HEX_START"/> and <see cref="BASE_MOVEMENT_EXTRA_HEX_END"/>
/// </summary>
public const float BASE_MOVEMENT_PER_HEX = 130;
public const int BASE_MOVEMENT_EXTRA_HEX_START = 2;
public const int BASE_MOVEMENT_EXTRA_HEX_END = 40;
/// <summary>
/// This is used to slightly debuff colony movement
/// </summary>
public const float CELL_COLONY_MOVEMENT_FORCE_MULTIPLIER = 0.98f;
/// <summary>
/// How much the default <see cref="BASE_CELL_DENSITY"/> has volume in a cell. This determines how much
/// additional organelles impact the cell. A normal organelle has a weight of 1 so if this value is 4 then the
/// base density has as much impact on the average density as 4 organelles.
/// </summary>
public const float BASE_CELL_DENSITY_VOLUME = 4;
public const float BASE_CELL_DENSITY = 1000;
public const float CONTEXTUAL_ONLY_MUSIC_CHANCE = 0.33f;
// Note that the rotation speed is reversed, i.e. lower values mean faster
public const float CELL_MAX_ROTATION = 8.0f;
public const float CELL_MIN_ROTATION = 0.10f;
public const float CELL_ROTATION_INFLECTION_INERTIA = 250000000.0f;
public const float CELL_ROTATION_RADIUS_FACTOR = 150.0f;
public const float CILIA_ROTATION_FACTOR = 120000000.0f;
public const float CILIA_RADIUS_FACTOR_MULTIPLIER = 8000000.0f;
public const float CELL_TURN_INFLECTION_RADIANS = 0.4f;
// TODO: remove if these stay unused
// // These speed values are also reversed like the above
// public const float CELL_COLONY_MAX_ROTATION_MULTIPLIER = 2.5f;
// public const float CELL_COLONY_MIN_ROTATION_MULTIPLIER = 0.05f;
// public const float CELL_COLONY_MAX_ROTATION_HELP = 0.5f;
// public const float CELL_COLONY_MEMBER_ROTATION_FACTOR_MULTIPLIER = 0.2f;
public const float CILIA_ENERGY_COST = 2.0f;
public const float CILIA_ROTATION_NEEDED_FOR_ATP_COST = 0.03f;
public const float CILIA_ROTATION_ENERGY_BASE_MULTIPLIER = 4.0f;
public const float CILIA_DEFAULT_ANIMATION_SPEED = 0.3f;
public const float CILIA_MIN_ANIMATION_SPEED = 0.15f;
public const float CILIA_MAX_ANIMATION_SPEED = 1.2f;
public const float CILIA_ROTATION_ANIMATION_SPEED_MULTIPLIER = 7.0f;
/// <summary>
/// Limits how often the cilia sample the rotation speed it should be at. Also, rate limits how often the cilia
/// pull physics is applied.
/// </summary>
public const float CILIA_ROTATION_SAMPLE_INTERVAL = 0.1f;
public const float CILIA_PULLING_FORCE = 200000.0f;
public const float CILIA_PULLING_FORCE_FIELD_RADIUS = 16.0f;
/// <summary>
/// How much each cilia increase <see cref="CILIA_PULLING_FORCE_FIELD_RADIUS"/>. This is now done like this to
/// avoid having to create a ton of physics sensors.
/// </summary>
public const float CILIA_PULL_RADIUS_PER_CILIA = 0.70f;
/// <summary>
/// 1 means that each cilia counts as 1 in the pulling force.
/// Smaller values mean diminishing returns.
/// </summary>
public const float CILIA_FORCE_EXPONENT_PER_CILIA = 0.9f;
public const float CILIA_PULLING_FORCE_FALLOFF_FACTOR = 0.05f;
public const float CILIA_CURRENT_GENERATION_ANIMATION_SPEED = 5.0f;
public const int MICROBE_SPAWN_RADIUS = 350;
public const int MICROBE_DESPAWN_RADIUS_SQUARED = (MICROBE_SPAWN_RADIUS + DESPAWN_RADIUS_OFFSET) *
(MICROBE_SPAWN_RADIUS + DESPAWN_RADIUS_OFFSET);
public const int CLOUD_SPAWN_RADIUS = 350;
/// <summary>
/// This controls how many entities over the entity limit we allow things to reproduce. This is so that even when
/// the spawn system has spawned things until the limit is full, the spawned things can still reproduce.
/// </summary>
public const float REPRODUCTION_ALLOW_EXCEED_ENTITY_LIMIT_MULTIPLIER = 1.15f;
/// <summary>
/// If the entity limit is over this once the player has reproduced, force despawning will happen
/// </summary>
public const float REPRODUCTION_PLAYER_ALLOWED_ENTITY_LIMIT_EXCEED = 1.25f;
/// <summary>
/// Once reproduced player copies take this much or more of the overall entity limit, they are preferred to
/// despawn first.
/// </summary>
public const float PREFER_DESPAWN_PLAYER_REPRODUCED_COPY_AFTER = 0.30f;
/// <summary>
/// Multiplier for how much individual cells in a colony contribute to the entity limit. Actually colonies seem
/// quite a bit heavier than normal microbes, as such this is set pretty high.
/// </summary>
public const float MICROBE_COLONY_MEMBER_ENTITY_WEIGHT_MULTIPLIER = 0.95f;
/// <summary>
/// Extra radius added to the spawn radius of things to allow them to move in the "wrong" direction a bit
/// without causing them to despawn instantly. Things despawn outside the despawn radius.
/// </summary>
public const int DESPAWN_RADIUS_OFFSET = 50;
public const float MIN_SPAWN_RADIUS_RATIO = 0.95f;
/// <summary>
/// The maximum force that can be applied by currents in the fluid system
/// </summary>
public const float MAX_FORCE_APPLIED_BY_CURRENTS = 2000;
/// <summary>
/// The multiplier to the force that currents apply to cells.
/// </summary>
public const float CURRENT_FORCE_CELL_MULTIPLIER = 15;
public const float CURRENT_COMPOUND_CLOUD_ADVECT_THRESHOLD = 0.15f;
public const int TRANSLATION_VERY_INCOMPLETE_THRESHOLD = 30;
public const int TRANSLATION_INCOMPLETE_THRESHOLD = 70;
public const float LIGHT_LEVEL_UPDATE_INTERVAL = 0.1f;
/// <summary>
/// When night is closer than this number of seconds and a cell spawns, it gets extra resources to survive.
/// </summary>
public const float INITIAL_RESOURCE_BUFF_WHEN_NIGHT_CLOSER_THAN = 30.0f;
/// <summary>
/// How many seconds of filling up during the day that a cell can be given when it is spawned close to or during
/// the night
/// </summary>
public const float NIGHT_RESOURCE_BUFF_MAX_FILL_SECONDS = 45.0f;
/// <summary>
/// How often the microbe AI processes each microbe
/// </summary>
public const float MICROBE_AI_THINK_INTERVAL = 0.3f;
/// <summary>
/// This is how often entities emitted signals from other entities are updated.
/// This is set relatively high to reduce the performance impact.
/// This is used, for example, for AI microbes to detect signalling agents.
/// </summary>
public const float ENTITY_SIGNAL_UPDATE_INTERVAL = 0.15f;
public const float ENTITY_LIGHT_REALISTIC_ATTENUATION = 2;
/// <summary>
/// Max lights a single entity should have. Note that compatibility renderer supports only 8 lights per mesh, so
/// we might need to increase that limit.
/// </summary>
public const int ENTITY_REASONABLE_MAX_LIGHTS = 6;
public const float ENTITY_BIOLUMINESCENCE_LIGHT_RANGE = 20;
public const int INITIAL_SPECIES_POPULATION = 100;
public const int INITIAL_FREEBUILD_POPULATION_VARIANCE_MIN = 0;
public const int INITIAL_FREEBUILD_POPULATION_VARIANCE_MAX = 400;
// Right now these are used for species split from the player
public const int INITIAL_SPLIT_POPULATION_MIN = 600;
public const int INITIAL_SPLIT_POPULATION_MAX = 2000;
public const string MICROBE_MOVEMENT_SOUND = "res://assets/sounds/soundeffects/microbe-movement-ambience.ogg";
public const string MICROBE_ENGULFING_MODE_SOUND = "res://assets/sounds/soundeffects/engulfment.ogg";
public const string MICROBE_BINDING_MODE_SOUND = "res://assets/sounds/soundeffects/binding.ogg";
public const float MICROBE_MOVEMENT_SOUND_EMIT_COOLDOWN = 1.3f;
public const float MICROBE_MOVEMENT_SOUND_MAX_BASE_VOLUME = 0.4f;
public const float MICROBE_MOVEMENT_SOUND_SPEED_SCALER = 30.0f;
public const float MICROBE_MOVEMENT_SOUND_MAX_VOLUME_SCALER = 4.0f;
// TODO: should this volume be actually 0?
public const float MICROBE_MOVEMENT_SOUND_START_VOLUME = 0.01f;
/// <summary>
/// Max number of concurrent audio players that may be used per entity.
/// </summary>
public const int MAX_CONCURRENT_SOUNDS_PER_ENTITY = 10;
public const float MICROBE_SOUND_MAX_DISTANCE = 300;
public const float MICROBE_SOUND_MAX_DISTANCE_SQUARED = MICROBE_SOUND_MAX_DISTANCE * MICROBE_SOUND_MAX_DISTANCE;
/// <summary>
/// Makes sounds played by the non-player cell a bit quieter. This is added because death sounds from other
/// entities can get overwhelming otherwise
/// </summary>
public const float NON_PLAYER_ENTITY_VOLUME_MULTIPLIER = 0.7f;
public const int MAX_CONCURRENT_SOUNDS = 100;
/// <summary>
/// Max number of concurrent audio players that may be spawned for UI sounds.
/// </summary>
public const int MAX_CONCURRENT_UI_AUDIO_PLAYERS = 10;
public const float CONTACT_PENETRATION_TO_BUMP_SOUND = 0.1f;
public const float INTERVAL_BETWEEN_SOUND_CACHE_CLEAR = 0.321f;
/// <summary>
/// How long to keep a played sound in memory in case it will be shortly played again
/// </summary>
public const float DEFAULT_SOUND_CACHE_TIME = 30;
public const float MEMORY_BEFORE_DISK_CACHE_TIME = 120;
public const float MEMORY_ONLY_CACHE_TIME = 300;
public const int MEMORY_PHOTO_CACHE_MAX_ITEMS = 250;
public const float MEMORY_PHOTO_CACHE_CLEAN_INTERVAL = 37;
public const float DISK_CACHE_CHECK_INTERVAL = 47;
public const float DISK_CACHE_IDLE_SAVE_INTERVAL = 53;
public const int DISK_CACHE_IDLE_SAVE_ITEMS = 3;
public const int DISK_CACHE_SAVES_PER_RUN = 5;
public const float DISK_CACHE_SAVE_RESUME_CHECK_INTERVAL = 1.17f;
public const float DISK_CACHE_DEFAULT_KEEP = 30 * 24 * 60 * 60;
public const long DISK_CACHE_DEFAULT_MAX_SIZE = MEBIBYTE * 1024;
public const int DISK_CACHE_MAX_DELETES_TO_QUEUE_AT_ONCE = 500;
// Base randomness for visual hashes to make different types not conflict
public const ulong VISUAL_HASH_CELL = 2106240777368515371UL;
public const ulong VISUAL_HASH_HEX_LAYOUT = 6086113318220891786UL;
public const ulong VISUAL_HASH_PATH = 16930532057563531237UL;
/// <summary>
/// Controls with how much speed agents are fired
/// </summary>
public const float AGENT_EMISSION_VELOCITY = 25.0f;
public const float OXYTOXY_DAMAGE = 25.0f;
public const float CYTOTOXIN_DAMAGE = 18.0f;
public const float OXYGEN_INHIBITOR_DAMAGE = 23.0f;
public const float CHANNEL_INHIBITOR_ATP_DEBUFF = 0.5f;
public const float CHANNEL_INHIBITOR_DEBUFF_DURATION = 15;
public const float MACROLIDE_BASE_MOVEMENT_DEBUFF = 0.8f;
public const float MACROLIDE_DEBUFF_DURATION = 5;
public const float TOXIN_TOXICITY_DAMAGE_MODIFIER_STRENGTH = 0.5f;
public const float DEFAULT_TOXICITY = 0.0f;
/// <summary>
/// Each oxygen using organelle in a cell increases damage caused by oxygen-inhibiting toxin by this amount,
/// up to a cap.
/// </summary>
public const float OXYGEN_INHIBITOR_DAMAGE_BUFF_PER_ORGANELLE = 0.05f;
public const float OXYGEN_INHIBITOR_DAMAGE_BUFF_MAX = 0.5f;
public const float OXYTOXY_DAMAGE_DEBUFF_PER_ORGANELLE = 0.05f;
public const float OXYTOXY_DAMAGE_DEBUFF_MAX = 0.75f;
/// <summary>
/// If the player has more than this much health, a single damage event cannot kill them. Instead, it leaves
/// just a bit of health (1% or 0.1 whichever is more).
/// </summary>
public const float PLAYER_INSTANT_KILL_PROTECTION_HEALTH_THRESHOLD = 5.0f;
/// <summary>
/// How much a cell's speed is slowed when travelling through slime
/// </summary>
public const float MUCILAGE_IMPEDE_FACTOR = 5.0f;
/// <summary>
/// How much a cell's speed is increased when secreting slime (scaling with secreted compound amount)
/// </summary>
public const float MUCILAGE_JET_FACTOR = 100000.0f;
/// <summary>
/// Minimum stored slime needed to start secreting
/// </summary>
public const float MUCILAGE_MIN_TO_VENT = 0.01f;
/// <summary>
/// Length in seconds for slime secretion cooldown
/// </summary>
public const float MUCILAGE_COOLDOWN_TIMER = 1.5f;
/// <summary>
/// How many times cell gets slowed down with mucocyst (slime jet upgrade) on
/// </summary>
public const float MUCOCYST_SPEED_MULTIPLIER = 0.01f;
/// <summary>
/// What fraction of the mucilage capacity is required to activate mucocyst (slime jet upgrade)
/// </summary>
public const float MUCOCYST_ACTIVATION_MUCILAGE_FRACTION = 0.5f;
/// <summary>
/// How much mucocyst (slime jet upgrade) drains mucilage per second
/// </summary>
public const float MUCOCYST_MUCILAGE_DRAIN = 0.7f;
public const float TOXIN_PROJECTILE_PHYSICS_SIZE = 1;
public const float TOXIN_PROJECTILE_PHYSICS_DENSITY = 700;
public const float CHUNK_PHYSICS_DAMPING = 0.2f;
public const float MICROBE_PHYSICS_DAMPING = 0.99f;
/// <summary>
/// This only really matters when cells are dead
/// </summary>
public const float MICROBE_PHYSICS_DAMPING_ANGULAR = 0.9f;
/// <summary>
/// Delay when a toxin hits or expires until it is destroyed. This is used to give some time for the effect to
/// fade so this must always be at least as long as how long the despawn effect takes visually
/// </summary>
public const float EMITTER_DESPAWN_DELAY = 3;
public const float AGENT_EMISSION_DISTANCE_OFFSET = 0.5f;
/// <summary>
/// How long a toxin projectile can fly for before despawning if it doesn't hit anything before that
/// </summary>
public const float EMITTED_AGENT_LIFETIME = 5.0f;
public const int MAX_EMITTED_AGENTS_ON_DEATH = 5;
/// <summary>
/// Percentage of the compounds that compose the organelle
/// released upon death (between 0.0 and 1.0).
/// </summary>
public const float COMPOUND_MAKEUP_RELEASE_FRACTION = 0.9f;
public const float COMPOUND_RELEASE_FRACTION = 0.9f;
public const float PHYSICS_ALLOWED_Y_AXIS_DRIFT = 0.1f;
/// <summary>
/// Buffers bigger than this number of elements will never be cached so if many entities track more than this
/// many collisions that's going to be bad in terms of memory allocations
/// </summary>
public const int MAX_COLLISION_CACHE_BUFFER_RETURN_SIZE = 50;
/// <summary>
/// How many buffers of similar length can be in the collision cache. This is quite high to ensure that basically
/// all entities' buffers can go to the cache for example when loading a save while in game. That is required
/// because most entities have the exact same buffer length.
/// </summary>
public const int MAX_COLLISION_CACHE_BUFFERS_OF_SIMILAR_LENGTH = 500;
/// <summary>
/// How many collisions each normal entity can detect at once (if more collisions happen during an update the
/// rest are lost and can't be detected by the game logic)
/// </summary>
public const int MAX_SIMULTANEOUS_COLLISIONS_SMALL = 8;
/// <summary>
/// A very small limit of collisions for entities that don't need to be able to detect many collisions. Note
/// that this is specifically picked to be lower by a power of two than the small limit to make collision
/// recording buffer cache work better (as it should hopefully put these two categories to separate buckets)
/// </summary>
public const int MAX_SIMULTANEOUS_COLLISIONS_TINY = 4;
/// <summary>
/// How many collisions a default sensor can detect at once
/// </summary>
public const int MAX_SIMULTANEOUS_COLLISIONS_SENSOR = 20;
public const int MAX_SIMULTANEOUS_COLLISIONS_RADIATION_SENSOR = 32;
/// <summary>
/// Cooldown between agent emissions, in seconds.
/// </summary>
public const float AGENT_EMISSION_COOLDOWN = 2.0f;
/// <summary>
/// The minimum amount of oxytoxy (or any agent) fired in one shot.
/// </summary>
public const float MINIMUM_AGENT_EMISSION_AMOUNT = MathUtils.EPSILON;
/// <summary>
/// The maximum amount of oxytoxy (or any agent) fired in one shot.
/// </summary>
public const float MAXIMUM_AGENT_EMISSION_AMOUNT = 2.0f;
/// <summary>
/// The time (in seconds) it takes a cloud being absorbed to halve its compounds.
/// </summary>
public const float CLOUD_ABSORPTION_HALF_LIFE = 0.02291666666f;
/// <summary>
/// How much of a compound is actually given to a cell when absorbed
/// </summary>
public const float ABSORPTION_RATIO = 0.0000125f;
/// <summary>
/// Should be greater than ABSORPTION_RATIO
/// </summary>
public const float SKIP_TRYING_TO_ABSORB_RATIO = 0.0002f;
/// <summary>
/// How much compounds a cell can vent per second
/// </summary>
public const float COMPOUNDS_TO_VENT_PER_SECOND = 5.0f;
public const float DEFAULT_MICROBE_VENT_THRESHOLD = 2.0f;
/// <summary>
/// If more chunks exist at once than this, then some are forced to despawn immediately. In reality the effective
/// value is higher as spawned and microbe corpse chunks have now their individual limits (so the real limit is
/// double this)
/// </summary>
public const int FLOATING_CHUNK_MAX_COUNT = 50;
public const float CHUNK_VENT_COMPOUND_MULTIPLIER = 5000.0f;
public const float MICROBE_VENT_COMPOUND_MULTIPLIER = 10000.0f;
public const float FLOATING_CHUNKS_DISSOLVE_SPEED = 0.3f;
public const int DESPAWNING_CHUNK_LIFETIME = 150;
public const float MEMBRANE_DISSOLVE_SPEED = 0.3f;
public const float INTERACTION_BUTTONS_FULL_UPDATE_INTERVAL = 0.1f;
public const int INTERACTION_BUTTONS_MAX_COUNT = 50;
public const float INTERACTION_BUTTON_DEFAULT_Y_OFFSET = 1.0f;
public const int INTERACTION_BUTTON_SIZE = 32;
public const int INTERACTION_BUTTON_X_PIXEL_OFFSET = -INTERACTION_BUTTON_SIZE / 2;
public const int INTERACTION_BUTTON_Y_PIXEL_OFFSET = -INTERACTION_BUTTON_SIZE / 2;
public const float INTERACTION_DEFAULT_VISIBILITY_DISTANCE = 20.0f;
public const float INTERACTION_DEFAULT_INTERACT_DISTANCE = 8.5f;
public const float INTERACTION_MAX_ANGLE_TO_VIEW = MathF.PI;
public const float WORLD_PROGRESS_BAR_FULL_UPDATE_INTERVAL = 0.1f;
public const float WORLD_PROGRESS_BAR_MAX_DISTANCE = 15.0f;
public const float WORLD_PROGRESS_BAR_MAX_COUNT = 15;
public const float WORLD_PROGRESS_BAR_DEFAULT_WIDTH = 125;
public const float WORLD_PROGRESS_BAR_MIN_WIDTH_TO_SHOW = 20;
public const float WORLD_PROGRESS_BAR_DEFAULT_HEIGHT = 18;
public const float WORLD_PROGRESS_BAR_MIN_HEIGHT = 6;
public const float WORLD_PROGRESS_BAR_DISTANCE_SIZE_SCALE = 1.0f;
public const float WORLD_PROGRESS_DEFAULT_Y_OFFSET = 3.5f;
public const float INVENTORY_DRAG_START_ALLOWANCE = 0.15f;
public const float NAME_LABELS_FULL_UPDATE_INTERVAL = 0.2f;
public const int NAME_LABELS_MAX_COUNT_PER_CATEGORY = 30;
public const float NAME_LABEL_VISIBILITY_DISTANCE = 300.0f;
/// <summary>
/// Maximum number of damage events allowed for an entity. More than this are not recorded and is an error.
/// </summary>
public const int MAX_DAMAGE_EVENTS = 1000;
/// <summary>
/// The maximum amount of ATP for a cell to take damage from lack of ATP. This used to be a hard-coded zero
/// but while under strain, ATP never reached that low, so an extra margin for ATP damage was added.
/// </summary>
public const float ATP_DAMAGE_THRESHOLD = 0.05f;
/// <summary>
/// Amount of health per second regenerated
/// </summary>
public const float HEALTH_REGENERATION_RATE = 1.5f;
/// <summary>
/// Time until a cell can regenerate after taking damage;
/// </summary>
public const float HEALTH_REGENERATION_COOLDOWN = 5.0f;
/// <summary>
/// This much damage has to be caused in a single instance to prevent health regen. This is pretty high to avoid
/// small trickle damage the player can't notice from preventing health regen.
/// </summary>
public const float HEALTH_REGEN_STOP_DAMAGE_THRESHOLD = 0.15f;
public const float HYDROGEN_SULFIDE_DAMAGE_INTERVAL = 0.75f;
public const float HYDROGEN_SULFIDE_DAMAGE_THESHOLD = 0.05f;
public const float HYDROGEN_SULFIDE_DAMAGE = 2.0f;
public const float HYDROGEN_SULFIDE_DAMAGE_COMPOUND_DRAIN = 0.2f;
public const float RADIATION_STRENGTH_MULTIPLIER = 0.02f;
/// <summary>
/// Fraction of radiation (from the max amount) that starts to cause damage?
/// </summary>
public const float RADIATION_DAMAGE_THRESHOLD = 0.6f;
public const float RADIATION_WARNING = RADIATION_DAMAGE_THRESHOLD - 0.15f;
public const float RADIATION_DAMAGE_MULTIPLIER = 5.1f;
/// <summary>
/// How often the radiation damage system runs (so the damage is applied)
/// </summary>
public const float RADIATION_DAMAGE_INTERVAL = 0.6f;
public const float RADIATION_NATURAL_DECAY = 0.03f;
public const float RADIATION_NATURAL_DECAY_WHEN_TAKING_DAMAGE = 5 * RADIATION_NATURAL_DECAY;
public const float RADIATION_PROTECTION_PER_ORGANELLE = 0.1f;
public const float ROCK_RADIATION_RADIUS = 25;
public const float SCREEN_DAMAGE_FLASH_THRESHOLD = 0.2f;
public const float SCREEN_DAMAGE_FLASH_DECAY_SPEED = 1.0f;
public const float MICROBE_CAMERA_MIN_HEIGHT = 3.0f;
public const float MICROBE_CAMERA_MAX_HEIGHT = 80.0f;
public const float MULTICELLULAR_CAMERA_MIN_HEIGHT = 8.0f;
/// <summary>
/// The highest that the dynamic multicellular camera max height can get.
/// </summary>
public const float MULTICELLULAR_CAMERA_MAX_HEIGHT = 180.0f;
/// <summary>
/// Cells need at least this much ATP to regenerate health passively. This is now less than one to allow cells
/// with 1 storage to regenerate health. As reaching exactly full storage of ATP is not really possible due to
/// constant osmoregulation and processes running.
/// </summary>
public const float HEALTH_REGENERATION_ATP_THRESHOLD = 0.9f;
/// <summary>
/// If a cell doesn't fulfil <see cref="HEALTH_REGENERATION_ATP_THRESHOLD"/> it can still be allowed if it is
/// this full on ATP (this allows small cells to heal with just 0.5 storage).
/// </summary>
public const float HEALTH_REGENERATION_ALTERNATIVE_ATP_FRACTION = 0.9f;
/// <summary>
/// How often in seconds ATP damage is checked and applied if cell has no ATP
/// </summary>
public const float ATP_DAMAGE_CHECK_INTERVAL = 0.9f;
/// <summary>
/// Because reproduction progress is most often time limited,
/// the bars can go to the reproduction ready state way too early, so this being false prevents that.
/// </summary>
public const bool ALWAYS_SHOW_STORED_COMPOUNDS_IN_REPRODUCTION_PROGRESS = false;
/// <summary>
/// Multiplier on how much total compounds can be absorbed by organelles to grow per second compared to the free
/// compounds amount. Value of 2 means that having available compounds in storage can make reproduction 2x the
/// speed of just using free compounds.
/// </summary>
public const float MICROBE_REPRODUCTION_MAX_COMPOUND_USE = 2.25f;
/// <summary>
/// Controls how many "free" compounds a microbe absorbs out of thin air (or water, really) per second for
/// reproduction use. Note this limit applies to all compounds combined, not to each individual compound type.
/// This is because it is way easier to implement that way.
/// </summary>
public const float MICROBE_REPRODUCTION_FREE_COMPOUNDS = 0.25f;
/// <summary>
/// Bonus per hex given to the free compound rate (<see cref="MICROBE_REPRODUCTION_FREE_COMPOUNDS"/>)
/// </summary>
public const float MICROBE_REPRODUCTION_FREE_RATE_FROM_HEX = 0.02f;
/// <summary>
/// A multiplier for <see cref="MICROBE_REPRODUCTION_MAX_COMPOUND_USE"/> and
/// <see cref="MICROBE_REPRODUCTION_FREE_COMPOUNDS"/> for multicellular microbes
/// </summary>
public const float MULTICELLULAR_REPRODUCTION_COMPOUND_MULTIPLIER = 2;
/// <summary>
/// How much ammonia a microbe needs on top of the organelle initial compositions to reproduce
/// </summary>
public const float MICROBE_REPRODUCTION_COST_BASE_AMMONIA = 16;
public const float MICROBE_REPRODUCTION_COST_BASE_PHOSPHATES = 16;
public const float MULTICELLULAR_BASE_REPRODUCTION_COST_MULTIPLIER = 1.3f;
/// <summary>
/// Determines how big of a fraction of damage (of total health)
/// is dealt to a microbe at a time when it is out of ATP.
/// </summary>
public const float NO_ATP_DAMAGE_FRACTION = 0.04f;
/// <summary>
/// Organelles won't take compounds if there is less available than this amount
/// </summary>
/// <remarks>
/// <para>
/// This is no longer zero as rounding can otherwise make compounds just disappear
/// </para>
/// </remarks>
public const float ORGANELLE_GROW_STORAGE_MUST_HAVE_AT_LEAST = 0.0001f;
/// <summary>
/// Cost of moving the rigidity slider by one step in the microbe editor
/// </summary>
public const int MEMBRANE_RIGIDITY_COST_PER_STEP = 2;
/// <summary>
/// Number used to convert between the value from the rigidity slider and the actual value
/// </summary>
public const float MEMBRANE_RIGIDITY_SLIDER_TO_VALUE_RATIO = 10;
/// <summary>
/// How much fully rigid membrane adds hitpoints
/// </summary>
public const float MEMBRANE_RIGIDITY_HITPOINTS_MODIFIER = 30;
/// <summary>
/// How much fully rigid membrane reduces movement factor of a cell
/// </summary>
public const float MEMBRANE_RIGIDITY_BASE_MOBILITY_MODIFIER = 0.1f;
/// <summary>
/// How much ATP does engulf mode cost per second
/// </summary>
public const float ENGULFING_ATP_COST_PER_SECOND = 1.5f;
/// <summary>
/// The speed reduction (multiplies the movement force) when a cell is in engulfing mode.
/// </summary>
public const float ENGULFING_MOVEMENT_MULTIPLIER = 0.588f;
/// <summary>
/// The minimum size ratio between a cell and a possible engulfing victim.
/// </summary>
public const float ENGULF_SIZE_RATIO_REQ = 1.5f;
public const float EUKARYOTIC_ENGULF_SIZE_MULTIPLIER = 2.0f;
/// <summary>
/// The duration for which an engulfable object can't be engulfed after being expelled.
/// </summary>
public const float ENGULF_EJECTED_COOLDOWN = 2.5f;
public const float ENGULF_EJECTION_VELOCITY = 3.0f;
/// <summary>
/// Offsets how far should the chunks for expelled partially digested objects be spawned from the membrane.
/// 0 means no offset and chunks are spawned directly on the membrane point.
/// </summary>
public const float EJECTED_PARTIALLY_DIGESTED_CELL_CORPSE_CHUNKS_SPAWN_OFFSET = 2.0f;
/// <summary>
/// The measure of which beyond this threshold an engulfable is considered partially digested.
/// Used to determine whether a cell should be able to heal after being expelled from engulfment.
/// </summary>
public const float PARTIALLY_DIGESTED_THRESHOLD = 0.8f;
/// <summary>
/// The maximum digestion progress in which an engulfable is considered fully digested. Do not change this.
/// It is assumed elsewhere that 1 means fully digested so this will break a bunch of stuff if you change this.
/// </summary>
public const float FULLY_DIGESTED_LIMIT = 1.0f;
/// <summary>
/// The speed of which a cell can absorb compounds from digestible engulfed objects.
/// </summary>
public const float ENGULF_COMPOUND_ABSORBING_PER_SECOND = 0.3f;
/// <summary>
/// How much compounds in relation to real compound amount can be absorbed from digestible engulfed objects.
/// </summary>
public const float ENGULF_BASE_COMPOUND_ABSORPTION_YIELD = 0.5f;
/// <summary>
/// How long can cell be in engulf mode after activating without ATP
/// </summary>
public const float ENGULF_NO_ATP_TIME = 3.0f;
/// <summary>
/// How much cell is damaged from engulfing while without ATP
/// </summary>
public const float ENGULF_NO_ATP_DAMAGE = 10.0f;
/// <summary>
/// If cell has less than this ATP, then it triggers forced mode enter and takes damage.
/// <see cref="Components.MicrobeControlHelpers.EnterEngulfModeForcedState"/>
/// </summary>
public const float ENGULF_NO_ATP_TRIGGER_THRESHOLD = 0.7f;
/// <summary>
/// On top of <see cref="ENGULF_NO_ATP_TRIGGER_THRESHOLD"/> ATP needs to be less than this fraction of storage.
/// This is to protect small cells that have only like max of 1 storage.
/// </summary>