-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathCStationType.cpp
2123 lines (1629 loc) · 56.8 KB
/
CStationType.cpp
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
// CStationType.cpp
//
// CStationType class
#include "PreComp.h"
#define ANIMATIONS_TAG CONSTLIT("Animations")
#define COMMUNICATIONS_TAG CONSTLIT("Communications")
#define COMPOSITE_TAG CONSTLIT("ImageComposite")
#define CONSTRUCTION_TAG CONSTLIT("Construction")
#define DEVICES_TAG CONSTLIT("Devices")
#define DOCKING_PORTS_TAG CONSTLIT("DockingPorts")
#define DOCK_SCREENS_TAG CONSTLIT("DockScreens")
#define ENCOUNTER_GROUP_TAG CONSTLIT("EncounterGroup")
#define ENCOUNTER_TYPE_TAG CONSTLIT("EncounterType")
#define ENCOUNTERS_TAG CONSTLIT("Encounters")
#define EVENTS_TAG CONSTLIT("Events")
#define HERO_IMAGE_TAG CONSTLIT("HeroImage")
#define IMAGE_TAG CONSTLIT("Image")
#define IMAGE_EFFECT_TAG CONSTLIT("ImageEffect")
#define IMAGE_LOOKUP_TAG CONSTLIT("ImageLookup")
#define IMAGE_SHIPWRECK_TAG CONSTLIT("ImageShipwreck")
#define IMAGE_VARIANTS_TAG CONSTLIT("ImageVariants")
#define ITEMS_TAG CONSTLIT("Items")
#define NAMES_TAG CONSTLIT("Names")
#define REINFORCEMENTS_TAG CONSTLIT("Reinforcements")
#define SATELLITES_TAG CONSTLIT("Satellites")
#define SHIP_TAG CONSTLIT("Ship")
#define SHIPS_TAG CONSTLIT("Ships")
#define STATION_TAG CONSTLIT("Station")
#define TABLE_TAG CONSTLIT("Table")
#define TRADE_TAG CONSTLIT("Trade")
#define ABANDONED_SCREEN_ATTRIB CONSTLIT("abandonedScreen")
#define ALERT_WHEN_ATTACKED_ATTRIB CONSTLIT("alertWhenAttacked")
#define ALERT_WHEN_DESTROYED_ATTRIB CONSTLIT("alertWhenDestroyed")
#define ALLOW_ENEMY_DOCKING_ATTRIB CONSTLIT("allowEnemyDocking")
#define ARMOR_ID_ATTRIB CONSTLIT("armorID")
#define BACKGROUND_PLANE_ATTRIB CONSTLIT("backgroundPlane")
#define BARRIER_EFFECT_ATTRIB CONSTLIT("barrierEffect")
#define BEACON_ATTRIB CONSTLIT("beacon")
#define BUILD_REINFORCEMENTS_ATTRIB CONSTLIT("buildReinforcements")
#define CAN_ATTACK_ATTRIB CONSTLIT("canAttack")
#define CHALLENGE_ATTRIB CONSTLIT("challenge")
#define CHANCE_ATTRIB CONSTLIT("chance")
#define CONSTRUCTION_RATE_ATTRIB CONSTLIT("constructionRate")
#define CONTROLLING_SOVEREIGN_ATTRIB CONSTLIT("controllingSovereign")
#define COUNT_ATTRIB CONSTLIT("count")
#define DEFAULT_BACKGROUND_ID_ATTRIB CONSTLIT("defaultBackgroundID")
#define DEST_ENTRY_POINT_ATTRIB CONSTLIT("destEntryPoint")
#define DEST_NODE_ATTRIB CONSTLIT("destNodeID")
#define DESTROY_WHEN_EMPTY_ATTRIB CONSTLIT("destroyWhenEmpty")
#define DOCK_SCREEN_ATTRIB CONSTLIT("dockScreen")
#define DOCKING_PORTS_ATTRIB CONSTLIT("dockingPorts")
#define ENEMY_EXCLUSION_RADIUS_ATTRIB CONSTLIT("enemyExclusionRadius")
#define EJECTA_ADJ_ATTRIB CONSTLIT("ejectaAdj")
#define EJECTA_TYPE_ATTRIB CONSTLIT("ejectaType")
#define EXPLOSION_TYPE_ATTRIB CONSTLIT("explosionType")
#define FIRE_RATE_ADJ_ATTRIB CONSTLIT("fireRateAdj")
#define FREQUENCY_ATTRIB CONSTLIT("frequency")
#define GATE_EFFECT_ATTRIB CONSTLIT("gateEffect")
#define GRAVITY_RADIUS_ATTRIB CONSTLIT("gravityRadius")
#define HIT_POINTS_ATTRIB CONSTLIT("hitPoints")
#define IMMUTABLE_ATTRIB CONSTLIT("immutable")
#define INACTIVE_ATTRIB CONSTLIT("inactive")
#define LEVEL_ATTRIB CONSTLIT("level")
#define LEVEL_FREQUENCY_ATTRIB CONSTLIT("levelFrequency")
#define LOCATION_CRITERIA_ATTRIB CONSTLIT("locationCriteria")
#define MASS_ATTRIB CONSTLIT("mass")
#define MAX_CONSTRUCTION_ATTRIB CONSTLIT("maxConstruction")
#define MAX_HIT_POINTS_ATTRIB CONSTLIT("maxHitPoints")
#define MAX_LIGHT_DISTANCE CONSTLIT("maxLightRadius")
#define MAX_STRUCTURAL_HIT_POINTS_ATTRIB CONSTLIT("maxStructuralHitPoints")
#define MIN_SHIPS_ATTRIB CONSTLIT("minShips")
#define MOBILE_ATTRIB CONSTLIT("mobile")
#define MULTI_HULL_ATTRIB CONSTLIT("multiHull")
#define NAME_ATTRIB CONSTLIT("name")
#define NO_BLACKLIST_ATTRIB CONSTLIT("noBlacklist")
#define NO_FRIENDLY_FIRE_ATTRIB CONSTLIT("noFriendlyFire")
#define NO_FRIENDLY_TARGET_ATTRIB CONSTLIT("noFriendlyTarget")
#define NO_MAP_DETAILS_ATTRIB CONSTLIT("noMapDetails")
#define NO_MAP_ICON_ATTRIB CONSTLIT("noMapIcon")
#define NO_MAP_LABEL_ATTRIB CONSTLIT("noMapLabel")
#define PAINT_LAYER_ATTRIB CONSTLIT("paintLayer")
#define RADIOACTIVE_ATTRIB CONSTLIT("radioactive")
#define RANDOM_ENCOUNTERS_ATTRIB CONSTLIT("randomEncounters")
#define REGEN_ATTRIB CONSTLIT("regen")
#define REPAIR_RATE_ATTRIB CONSTLIT("repairRate")
#define REVERSE_ARTICLE_ATTRIB CONSTLIT("reverseArticle")
#define SCALE_ATTRIB CONSTLIT("scale")
#define SHIP_ENCOUNTER_ATTRIB CONSTLIT("shipEncounter")
#define SHIP_REGEN_ATTRIB CONSTLIT("shipRegen")
#define SHIP_REPAIR_RATE_ATTRIB CONSTLIT("shipRepairRate")
#define SHIPWRECK_UNID_ATTRIB CONSTLIT("shipwreckID")
#define SIGN_ATTRIB CONSTLIT("sign")
#define SIZE_ATTRIB CONSTLIT("size")
#define SOVEREIGN_ATTRIB CONSTLIT("sovereign")
#define SPACE_COLOR_ATTRIB CONSTLIT("spaceColor")
#define STANDING_COUNT_ATTRIB CONSTLIT("standingCount")
#define STEALTH_ATTRIB CONSTLIT("stealth")
#define STRUCTURAL_HIT_POINTS_ATTRIB CONSTLIT("structuralHitPoints")
#define TIME_STOP_IMMUNE_ATTRIB CONSTLIT("timeStopImmune")
#define TYPE_ATTRIB CONSTLIT("type")
#define UNID_ATTRIB CONSTLIT("UNID")
#define UNIQUE_ATTRIB CONSTLIT("unique")
#define VIRTUAL_ATTRIB CONSTLIT("virtual")
#define WALL_ATTRIB CONSTLIT("barrier")
#define X_ATTRIB CONSTLIT("x")
#define Y_ATTRIB CONSTLIT("y")
#define LARGE_DAMAGE_IMAGE_ID_ATTRIB CONSTLIT("largeDamageImageID")
#define LARGE_DAMAGE_WIDTH_ATTRIB CONSTLIT("largeDamageWidth")
#define LARGE_DAMAGE_HEIGHT_ATTRIB CONSTLIT("largeDamageHeight")
#define LARGE_DAMAGE_COUNT_ATTRIB CONSTLIT("largeDamageCount")
#define MEDIUM_DAMAGE_IMAGE_ID_ATTRIB CONSTLIT("mediumDamageImageID")
#define MEDIUM_DAMAGE_WIDTH_ATTRIB CONSTLIT("mediumDamageWidth")
#define MEDIUM_DAMAGE_HEIGHT_ATTRIB CONSTLIT("mediumDamageHeight")
#define MEDIUM_DAMAGE_COUNT_ATTRIB CONSTLIT("mediumDamageCount")
#define STAR_SCALE CONSTLIT("star")
#define WORLD_SCALE CONSTLIT("world")
#define STRUCTURE_SCALE CONSTLIT("structure")
#define SHIP_SCALE CONSTLIT("ship")
#define FLOTSAM_SCALE CONSTLIT("flotsam")
#define UNIQUE_IN_SYSTEM CONSTLIT("inSystem")
#define UNIQUE_IN_UNIVERSE CONSTLIT("inUniverse")
#define EVENT_ON_MINING CONSTLIT("OnMining")
#define FIELD_ABANDONED_DOCK_SCREEN CONSTLIT("abandonedDockScreen")
#define FIELD_ARMOR_CLASS CONSTLIT("armorClass")
#define FIELD_ARMOR_LEVEL CONSTLIT("armorLevel")
#define FIELD_BALANCE CONSTLIT("balance")
#define FIELD_CAN_ATTACK CONSTLIT("canAttack")
#define FIELD_CATEGORY CONSTLIT("category")
#define FIELD_DEFENDER_STRENGTH CONSTLIT("defenderStrength")
#define FIELD_DOCK_SCREEN CONSTLIT("dockScreen")
#define FIELD_EXPLOSION_TYPE CONSTLIT("explosionType")
#define FIELD_FIRE_RATE_ADJ CONSTLIT("fireRateAdj")
#define FIELD_HITS_TO_DESTROY CONSTLIT("hitsToDestroy") // # of hits by std level weapon to destroy station
#define FIELD_INSTALL_DEVICE_MAX_LEVEL CONSTLIT("installDeviceMaxLevel")
#define FIELD_HP CONSTLIT("hp")
#define FIELD_LEVEL CONSTLIT("level")
#define FIELD_LOCATION_CRITERIA CONSTLIT("locationCriteria")
#define FIELD_MAX_LIGHT_RADIUS CONSTLIT("maxLightRadius")
#define FIELD_NAME CONSTLIT("name")
#define FIELD_REGEN CONSTLIT("regen") // hp repaired per 180 ticks
#define FIELD_SATELLITE_STRENGTH CONSTLIT("satelliteStrength")
#define FIELD_SIZE CONSTLIT("size")
#define FIELD_TREASURE_BALANCE CONSTLIT("treasureBalance") // 100 = treasure appropriate for defenses, 200 = twice as much treasure
#define FIELD_TREASURE_VALUE CONSTLIT("treasureValue")
#define FIELD_WEAPON_STRENGTH CONSTLIT("weaponStrength") // Strength of weapons (100 = level weapon @ 1/4 fire rate).
#define PROPERTY_LEVEL_FREQUENCY CONSTLIT("levelFrequency")
#define PROPERTY_NAME CONSTLIT("name")
#define PROPERTY_SHOWS_UNEXPLORED_ANNOTATION CONSTLIT("showsUnexploredAnnotation")
#define PROPERTY_SOVEREIGN CONSTLIT("sovereign")
#define PROPERTY_SOVEREIGN_NAME CONSTLIT("sovereignName")
#define PROPERTY_SYSTEM_CRITERIA CONSTLIT("systemCriteria")
#define VALUE_FALSE CONSTLIT("false")
#define VALUE_SHIPWRECK CONSTLIT("shipwreck")
#define VALUE_TRUE CONSTLIT("true")
#define MAX_ATTACK_DISTANCE (g_KlicksPerPixel * 512)
#define SPECIAL_IS_ENEMY_OF CONSTLIT("isEnemyOf:")
#define SPECIAL_IS_SHIP_ENCOUNTER CONSTLIT("isShipEncounter:")
#define SPECIAL_IS_STATION_ENCOUNTER CONSTLIT("isStationEncounter:")
#define SPECIAL_SCALE CONSTLIT("scale:")
#define SPECIAL_SIZE_CLASS CONSTLIT("sizeClass:")
#define SPECIAL_VALUE_TRUE CONSTLIT("true")
#define ON_CREATE_EVENT CONSTLIT("OnCreate")
const Metric TREASURE_BALACE_POWER = 0.7;
struct SSizeData
{
int iMinSize;
int iMaxSize;
};
// NOTE: These must match the values of ESizeClass
static SSizeData SIZE_DATA[] =
{
{ 0, 0, },
{ 1, 24, },
{ 25, 74, },
{ 75, 299, },
{ 300, 749, },
{ 750, 1499, },
{ 1500, 2999, },
{ 3000, 4499, },
{ 4500, 7499, },
{ 7500, 14999, },
{ 15000, 29999, },
{ 30000, 74999, },
{ 75000, 149999, },
{ 150000, 1000000, },
};
// Standard station table
struct SStdStationDesc
{
CurrencyValue dwTreasureValue; // Std value of treasure at this level
};
static SStdStationDesc STD_STATION_DATA[] =
{
{ 0, },
{ 750, },
{ 1000, },
{ 1500, },
{ 2000, },
{ 4000, },
{ 8000, },
{ 16000, },
{ 32000, },
{ 64000, },
{ 128000, },
{ 256000, },
{ 512000, },
{ 1000000, },
{ 2000000, },
{ 4100000, },
{ 8200000, },
{ 16400000, },
{ 32800000, },
{ 65500000, },
{ 131000000, },
{ 262000000, },
{ 524000000, },
{ 1000000000, },
{ 2100000000, },
{ 4200000000, },
};
CIntegralRotationDesc CStationType::m_DefaultRotation;
CStationType::CStationType (void) :
m_pDesc(NULL),
m_pInitialShips(NULL),
m_pReinforcements(NULL),
m_pEncounters(NULL),
m_iEncounterFrequency(ftNotRandom),
m_pSatellitesDesc(NULL),
m_pConstruction(NULL),
m_iShipConstructionRate(0),
m_iMaxConstruction(0),
m_Devices(NULL),
m_iAnimationsCount(0),
m_pAnimations(NULL),
m_pItems(NULL),
m_pTrade(NULL)
// CStationType constructor
{
}
CStationType::~CStationType (void)
// CStationType destructor
{
if (m_Devices)
delete [] m_Devices;
if (m_pItems)
delete m_pItems;
if (m_pInitialShips)
delete m_pInitialShips;
if (m_pReinforcements)
delete m_pReinforcements;
if (m_pEncounters)
delete m_pEncounters;
if (m_pAnimations)
delete [] m_pAnimations;
if (m_pTrade)
delete m_pTrade;
}
void CStationType::AddTypesUsedByXML (CXMLElement *pElement, TSortMap<DWORD, bool> *retTypesUsed)
// AddTypesUsedByXML
//
// Add type used by the <Station> XML element (recursively)
{
int i;
if (strEquals(pElement->GetTag(), STATION_TAG))
retTypesUsed->SetAt(pElement->GetAttributeInteger(TYPE_ATTRIB), true);
for (i = 0; i < pElement->GetContentElementCount(); i++)
AddTypesUsedByXML(pElement->GetContentElement(i), retTypesUsed);
}
Metric CStationType::CalcBalance (void) const
// CalcBalance
//
// Calculates the station defense balance assuming the station is at the given level.
{
// Compute balance, if necessary
if (!m_fBalanceValid)
{
int iLevel = GetLevel();
if (iLevel <= 0 || iLevel > MAX_TECH_LEVEL)
return 0.0;
m_rCombatBalance = (CalcDefenderStrength(iLevel) + CalcWeaponStrength(iLevel)) / 3.5;
m_rCombatBalance *= Min(2.0, sqrt((Metric)CalcHitsToDestroy(iLevel) / 50.0));
}
return m_rCombatBalance;
}
Metric CStationType::CalcDefenderStrength (int iLevel) const
// CalcDefenderStrength
//
// Returns the strength of station defenders
// 1.0 = 1 defender of station level.
{
Metric rTotal = 0.0;
// Add ship defenders
if (m_pInitialShips)
rTotal += m_pInitialShips->GetAverageLevelStrength(iLevel);
// Add satellite defenses
if (m_pSatellitesDesc)
rTotal += CalcSatelliteStrength(m_pSatellitesDesc, iLevel);
// Done
return rTotal;
}
int CStationType::CalcHitsToDestroy (int iLevel) const
// CalcHitsToDestroy
//
// Returns the number of hits that it would take to destroy the station when
// hit by a standard weapon of the given level.
{
Metric rTotalHits = m_HullDesc.CalcHitsToDestroy(iLevel);
// Add hits to destroy satellites
if (m_pSatellitesDesc)
rTotalHits += CalcSatelliteHitsToDestroy(m_pSatellitesDesc, iLevel);
// DOne
return (int)rTotalHits;
}
Metric CStationType::CalcMaxAttackDistance (void)
// CalcMaxAttackDistance
//
// Initializes m_rMaxAttackDistance, if necessary.
{
if (m_fCalcMaxAttackDist
&& g_pUniverse->GetDesignCollection().IsBindComplete())
{
Metric rBestRange = MAX_ATTACK_DISTANCE;
for (int i = 0; i < m_iDevicesCount; i++)
{
if (m_Devices[i].GetCategory() == itemcatWeapon
|| m_Devices[i].GetCategory() == itemcatLauncher)
{
CItem Item(m_Devices[i].GetClass()->GetItemType(), 1);
Metric rRange = m_Devices[i].GetMaxRange(CItemCtx(Item));
if (rRange > rBestRange)
rBestRange = rRange;
}
}
m_rMaxAttackDistance = rBestRange;
m_fCalcMaxAttackDist = false;
}
return m_rMaxAttackDistance;
}
Metric CStationType::CalcSatelliteHitsToDestroy (CXMLElement *pSatellites, int iLevel, bool bIgnoreChance)
// CalcSatelliteHitsToDestroy
//
// Calculate the total hits to destroy all satellites
{
int i;
const CString &sTag = pSatellites->GetTag();
int iChance;
Metric rChanceAdj;
if (!bIgnoreChance
&& pSatellites->FindAttributeInteger(CHANCE_ATTRIB, &iChance))
rChanceAdj = (Metric)iChance / 100.0;
else
rChanceAdj = 1.0;
Metric rTotalHits = 0.0;
if (strEquals(sTag, SHIP_TAG))
{
// Skip ships
}
else if (strEquals(sTag, STATION_TAG))
{
CStationType *pStationType = g_pUniverse->FindStationType((DWORD)pSatellites->GetAttributeInteger(TYPE_ATTRIB));
if (pStationType == NULL || !pStationType->CanAttack())
return 0.0;
rTotalHits += (rChanceAdj * pStationType->CalcHitsToDestroy(iLevel));
}
else if (strEquals(sTag, TABLE_TAG))
{
int iTotalChance = 0;
for (i = 0; i < pSatellites->GetContentElementCount(); i++)
iTotalChance += pSatellites->GetContentElement(i)->GetAttributeInteger(CHANCE_ATTRIB);
if (iTotalChance > 0)
{
for (i = 0; i < pSatellites->GetContentElementCount(); i++)
rTotalHits += rChanceAdj * CalcSatelliteHitsToDestroy(pSatellites->GetContentElement(i), iLevel, true)
* (Metric)pSatellites->GetContentElement(i)->GetAttributeInteger(CHANCE_ATTRIB)
/ 100.0;
}
}
else
{
Metric rCount = 1.0;
CString sAttrib;
if (pSatellites->FindAttribute(COUNT_ATTRIB, &sAttrib))
{
DiceRange Count;
Count.LoadFromXML(sAttrib);
rCount = Count.GetAveValueFloat();
}
for (i = 0; i < pSatellites->GetContentElementCount(); i++)
rTotalHits += rCount * rChanceAdj * CalcSatelliteHitsToDestroy(pSatellites->GetContentElement(i), iLevel);
}
// Done
return rTotalHits;
}
Metric CStationType::CalcSatelliteStrength (CXMLElement *pSatellites, int iLevel, bool bIgnoreChance)
// CalcSatelliteStrength
//
// Computes the total strength of satellites
// 100 = 1 satellite at station level.
{
int i;
const CString &sTag = pSatellites->GetTag();
int iChance;
Metric rChanceAdj;
if (!bIgnoreChance
&& pSatellites->FindAttributeInteger(CHANCE_ATTRIB, &iChance))
rChanceAdj = (Metric)iChance / 100.0;
else
rChanceAdj = 1.0;
Metric rTotal = 0.0;
if (strEquals(sTag, SHIP_TAG))
{
// Load generator
SDesignLoadCtx Ctx;
IShipGenerator *pGenerator;
if (IShipGenerator::CreateFromXML(Ctx, pSatellites, &pGenerator) != NOERROR)
return 0.0;
if (pGenerator->OnDesignLoadComplete(Ctx) != NOERROR)
{
delete pGenerator;
return 0.0;
}
rTotal += rChanceAdj * pGenerator->GetAverageLevelStrength(iLevel);
delete pGenerator;
}
else if (strEquals(sTag, STATION_TAG))
{
CStationType *pStationType = g_pUniverse->FindStationType((DWORD)pSatellites->GetAttributeInteger(TYPE_ATTRIB));
if (pStationType == NULL)
return 0.0;
rTotal += rChanceAdj * pStationType->GetLevelStrength(iLevel);
}
else if (strEquals(sTag, TABLE_TAG))
{
int iTotalChance = 0;
for (i = 0; i < pSatellites->GetContentElementCount(); i++)
iTotalChance += pSatellites->GetContentElement(i)->GetAttributeInteger(CHANCE_ATTRIB);
if (iTotalChance > 0)
{
for (i = 0; i < pSatellites->GetContentElementCount(); i++)
rTotal += rChanceAdj * CalcSatelliteStrength(pSatellites->GetContentElement(i), iLevel, true)
* (Metric)pSatellites->GetContentElement(i)->GetAttributeInteger(CHANCE_ATTRIB)
/ 100.0;
}
}
else
{
Metric rCount = 1.0;
CString sAttrib;
if (pSatellites->FindAttribute(COUNT_ATTRIB, &sAttrib))
{
DiceRange Count;
Count.LoadFromXML(sAttrib);
rCount = Count.GetAveValueFloat();
}
for (i = 0; i < pSatellites->GetContentElementCount(); i++)
rTotal += rCount * rChanceAdj * CalcSatelliteStrength(pSatellites->GetContentElement(i), iLevel);
}
// Done
return rTotal;
}
Metric CStationType::CalcSatelliteTreasureValue (CXMLElement *pSatellites, int iLevel, bool bIgnoreChance)
// CalcSatelliteTreasureValue
//
// Computes the total treasure value in satellites
{
int i;
const CString &sTag = pSatellites->GetTag();
int iChance;
Metric rChanceAdj;
if (!bIgnoreChance
&& pSatellites->FindAttributeInteger(CHANCE_ATTRIB, &iChance))
rChanceAdj = (Metric)iChance / 100.0;
else
rChanceAdj = 1.0;
Metric rTotal = 0.0;
if (strEquals(sTag, SHIP_TAG))
{
// Skip
}
else if (strEquals(sTag, STATION_TAG))
{
CStationType *pStationType = g_pUniverse->FindStationType((DWORD)pSatellites->GetAttributeInteger(TYPE_ATTRIB));
if (pStationType == NULL)
return 0.0;
Metric rTreasure = rChanceAdj * pStationType->CalcTreasureValue(iLevel);
// Treasure in asteroids should be discounted (since not everyone has
// a mining cannon).
if (!pStationType->CanAttack()
&& pStationType->HasAttribute(CONSTLIT("asteroid")))
rTreasure *= 0.2;
rTotal += rTreasure;
}
else if (strEquals(sTag, TABLE_TAG))
{
int iTotalChance = 0;
for (i = 0; i < pSatellites->GetContentElementCount(); i++)
iTotalChance += pSatellites->GetContentElement(i)->GetAttributeInteger(CHANCE_ATTRIB);
if (iTotalChance > 0)
{
for (i = 0; i < pSatellites->GetContentElementCount(); i++)
rTotal += rChanceAdj * CalcSatelliteTreasureValue(pSatellites->GetContentElement(i), iLevel, true)
* (Metric)pSatellites->GetContentElement(i)->GetAttributeInteger(CHANCE_ATTRIB)
/ 100.0;
}
}
else
{
Metric rCount = 1.0;
CString sAttrib;
if (pSatellites->FindAttribute(COUNT_ATTRIB, &sAttrib))
{
DiceRange Count;
Count.LoadFromXML(sAttrib);
rCount = Count.GetAveValueFloat();
}
for (i = 0; i < pSatellites->GetContentElementCount(); i++)
rTotal += rCount * rChanceAdj * CalcSatelliteTreasureValue(pSatellites->GetContentElement(i), iLevel);
}
// Done
return rTotal;
}
Metric CStationType::CalcTreasureValue (int iLevel) const
// CalcTreasureValue
//
// Calculates the value of total treasure, include treasure on satellites.
{
Metric rTotal = 0.0;
if (m_pItems)
rTotal += m_pItems->GetAverageValue(iLevel);
if (m_pSatellitesDesc)
rTotal += CalcSatelliteTreasureValue(m_pSatellitesDesc, iLevel);
return rTotal;
}
Metric CStationType::CalcWeaponStrength (int iLevel) const
// CalcWeaponStrength
//
// Computes the total strength of all station weapons.
// 1.0 = level weapon at 1/4 fire rate.
{
int i;
// Start by adding up all weapons.
Metric rTotal = 0.0;
for (i = 0; i < m_iDevicesCount; i++)
{
if (m_Devices[i].IsEmpty()
|| (m_Devices[i].GetCategory() != itemcatWeapon
&& m_Devices[i].GetCategory() != itemcatLauncher))
continue;
CDeviceClass *pDeviceClass = m_Devices[i].GetClass();
int iDevLevel = pDeviceClass->GetLevel();
// Lower level weapons count less; higher level weapons count more.
rTotal += ::CalcLevelDiffStrength(iDevLevel - iLevel);
}
// Adjust for fire rate. Double the fire rate means double the strength.
rTotal *= (40.0 / (Metric)m_iFireRateAdj);
// Done
return rTotal;
}
bool CStationType::FindDataField (const CString &sField, CString *retsValue) const
// FindDataField
//
// Returns meta-data
{
if (m_HullDesc.FindDataField(sField, retsValue))
return true;
else if (strEquals(sField, FIELD_ABANDONED_DOCK_SCREEN))
*retsValue = m_pAbandonedDockScreen.GetStringUNID(const_cast<CStationType *>(this));
else if (strEquals(sField, FIELD_BALANCE))
*retsValue = strFromInt((int)(CalcBalance() * 100.0));
else if (strEquals(sField, FIELD_CATEGORY))
{
if (!CanBeEncounteredRandomly())
*retsValue = CONSTLIT("04-Not Random");
else if (HasLiteralAttribute(CONSTLIT("debris")))
*retsValue = CONSTLIT("03-Debris");
else if (HasLiteralAttribute(CONSTLIT("enemy")))
*retsValue = CONSTLIT("02-Enemy");
else if (HasLiteralAttribute(CONSTLIT("friendly")))
*retsValue = CONSTLIT("01-Friendly");
else
*retsValue = CONSTLIT("04-Not Random");
}
else if (strEquals(sField, FIELD_DEFENDER_STRENGTH))
*retsValue = strFromInt((int)(100.0 * CalcDefenderStrength(GetLevel())));
else if (strEquals(sField, FIELD_DOCK_SCREEN))
*retsValue = m_pFirstDockScreen.GetStringUNID(const_cast<CStationType *>(this));
else if (strEquals(sField, FIELD_LEVEL))
*retsValue = strFromInt(GetLevel());
else if (strEquals(sField, FIELD_LOCATION_CRITERIA))
*retsValue = GetLocationCriteria();
else if (strEquals(sField, FIELD_NAME))
*retsValue = GetNounPhrase();
else if (strEquals(sField, FIELD_FIRE_RATE_ADJ))
*retsValue = strFromInt(10000 / m_iFireRateAdj);
else if (strEquals(sField, FIELD_HITS_TO_DESTROY))
*retsValue = strFromInt(CalcHitsToDestroy(GetLevel()));
else if (strEquals(sField, FIELD_INSTALL_DEVICE_MAX_LEVEL))
{
int iMaxLevel = (m_pTrade ? m_pTrade->GetMaxLevelMatched(serviceInstallDevice) : -1);
*retsValue = (iMaxLevel != -1 ? strFromInt(iMaxLevel) : NULL_STR);
}
else if (strEquals(sField, FIELD_CAN_ATTACK))
*retsValue = (CanAttack() ? VALUE_TRUE : VALUE_FALSE);
else if (strEquals(sField, FIELD_EXPLOSION_TYPE))
{
if (m_pExplosionType)
{
CDeviceClass *pClass = g_pUniverse->FindDeviceClass((DWORD)strToInt(m_pExplosionType->GetUNID(), 0));
CWeaponClass *pWeapon = (pClass ? pClass->AsWeaponClass() : NULL);
if (pWeapon)
{
*retsValue = pWeapon->GetItemType()->GetNounPhrase();
return true;
}
}
*retsValue = CONSTLIT("none");
}
else if (strEquals(sField, FIELD_MAX_LIGHT_RADIUS))
*retsValue = strFromInt(m_iMaxLightDistance);
else if (strEquals(sField, FIELD_SATELLITE_STRENGTH))
*retsValue = strFromInt((m_pSatellitesDesc ? (int)(100.0 * CalcSatelliteStrength(m_pSatellitesDesc, GetLevel())) : 0));
else if (strEquals(sField, FIELD_SIZE))
*retsValue = strFromInt(m_iSize);
else if (strEquals(sField, FIELD_TREASURE_BALANCE))
{
int iLevel = GetLevel();
Metric rExpected = (Metric)GetBalancedTreasure();
Metric rTreasure = CalcTreasureValue(iLevel);
*retsValue = strFromInt((int)(100.0 * (rExpected > 0.0 ? rTreasure / rExpected : 0.0)));
}
else if (strEquals(sField, FIELD_TREASURE_VALUE))
*retsValue = strFromInt((int)CalcTreasureValue(GetLevel()));
else if (strEquals(sField, FIELD_WEAPON_STRENGTH))
*retsValue = strFromInt((int)(100.0 * CalcWeaponStrength(GetLevel())));
else
return CDesignType::FindDataField(sField, retsValue);
return true;
}
CurrencyValue CStationType::GetBalancedTreasure (void) const
// GetBalancedTreasure
//
// Returns the value of treasure (in credits) for this station that would
// balance against its difficulty.
{
return (CurrencyValue)(pow(CalcBalance(), TREASURE_BALACE_POWER) * (Metric)STD_STATION_DATA[GetLevel()].dwTreasureValue);
}
CCommunicationsHandler *CStationType::GetCommsHandler (void)
// GetCommsHandler
//
// Returns the comms handler to use
{
CDesignType *pParent = GetInheritFrom();
CCommunicationsHandler *pParentHandler;
if (pParent && (pParentHandler = pParent->GetCommsHandler()))
{
if (!m_fCommsHandlerInit)
{
m_CommsHandler.Merge(m_OriginalCommsHandler);
m_CommsHandler.Merge(*pParentHandler);
m_fCommsHandlerInit = true;
}
return (m_CommsHandler.GetCount() ? &m_CommsHandler : NULL);
}
else
return (m_OriginalCommsHandler.GetCount() ? &m_OriginalCommsHandler : NULL);
}
CSovereign *CStationType::GetControllingSovereign (void)
// GetControllingSovereign
//
// Returns the sovereign that controls the station
{
if (m_pControllingSovereign)
return m_pControllingSovereign;
else
return m_pSovereign;
}
const CStationEncounterDesc &CStationType::GetEncounterDesc (void) const
// GetEncounterDesc
//
// Get the encounter descriptor for this station.
{
// See if the adventure overrides our encounter descriptor
CAdventureDesc *pAdventure = g_pUniverse->GetCurrentAdventureDesc();
const CStationEncounterDesc *pDesc = (pAdventure ? pAdventure->GetEncounterDesc(GetUNID()) : NULL);
if (pDesc)
return *pDesc;
// Otherwise, we return our own.
return m_RandomPlacement;
}
int CStationType::GetLevel (int *retiMinLevel, int *retiMaxLevel) const
// GetLevel
//
// Returns the average level of the station.
//
// NOTE: We don't return a level range yet because we're not sure of the
// backwards compatibility issues.
{
int i;
// If necessary, calculate level.
if (m_iLevel == 0)
{
m_iLevel = GetEncounterDesc().CalcLevelFromFrequency();
if (m_iLevel == 0)
{
// Take the highest level of armor or devices
m_iLevel = m_HullDesc.GetArmorLevel();
for (i = 0; i < m_iDevicesCount; i++)
{
if (!m_Devices[i].IsEmpty())
{
int iDeviceLevel = m_Devices[i].GetClass()->GetLevel();
if (iDeviceLevel > m_iLevel)
m_iLevel = iDeviceLevel;
}
}
}
}
// Return
if (retiMinLevel) *retiMinLevel = m_iLevel;
if (retiMaxLevel) *retiMaxLevel = m_iLevel;
return m_iLevel;
}
Metric CStationType::GetLevelStrength (int iLevel)
// GetLevelStrength
//
// Returns the level strength of the given station (relative to iLevel).
// 1.0 = station with level appropriate weapon and 25 hits to destroy.
{
Metric rTotal = 0.0;
// Strength is based on weapons and ships
rTotal = CalcWeaponStrength(iLevel) + CalcDefenderStrength(iLevel);
// Adjust by armor. 1.0 = 25 hits to destroy.
rTotal *= (CalcHitsToDestroy(iLevel) / 25.0);
// Done
return rTotal;
}
CString CStationType::GetNamePattern (DWORD dwNounFormFlags, DWORD *retdwFlags) const
// GetNamePattern
//
// Returns the noun pattern.
{
return m_Name.GetConstantName(retdwFlags);
}
IShipGenerator *CStationType::GetReinforcementsTable (void)
// GetReinforcementsTable
//
// Return the reinforcements table.
{
// If we have a ship count structure, then we always use the main ship
// table.
if (m_DefenderCount.GetCountType() == CShipChallengeDesc::countStanding)
return m_pInitialShips;
// Otherwise, if we have an explicit reinforcements table, use that.
else if (m_pReinforcements)
return m_pReinforcements;
// Otherwise, we use the main table.
else
return m_pInitialShips;
}
const CIntegralRotationDesc &CStationType::GetRotationDesc (void)
// GetRotationDesc
//
// Returns the rotation parameters.
{
if (m_DefaultRotation.GetFrameCount() != 360)
m_DefaultRotation.Init(360);
return m_DefaultRotation;
}
bool CStationType::IsSizeClass (ESizeClass iClass) const
// IsSizeClass
//
// Returns TRUE if we are the given size class.
{
switch (GetScale())
{
case scaleWorld:
return (iClass >= worldSizeA && iClass <= worldSizeM
&& m_iSize >= SIZE_DATA[iClass].iMinSize
&& m_iSize <= SIZE_DATA[iClass].iMaxSize);
default:
return false;
}
}
void CStationType::MarkImages (const CCompositeImageSelector &Selector, const CCompositeImageModifiers &Modifiers)
// MarkImages
//
// Marks images used by the station
{
m_Image.MarkImage(Selector, Modifiers);
// Cache the destroyed station image, if necessary
if (HasWreckImage())
{
CCompositeImageModifiers Modifiers;
Modifiers.SetStationDamage();
m_Image.MarkImage(Selector, Modifiers);
}