1 package cz.cuni.amis.pogamut.ut2004.agent.module.sensomotoric;
2
3 import java.util.Collections;
4 import java.util.HashMap;
5 import java.util.Map;
6 import java.util.logging.Level;
7
8 import cz.cuni.amis.pogamut.base.agent.module.SensomotoricModule;
9 import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
10 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
11 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
12 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent;
13 import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
14 import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
15 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.AgentInfo;
16 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.ItemDescriptors;
17 import cz.cuni.amis.pogamut.ut2004.bot.IUT2004BotController;
18 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
19 import cz.cuni.amis.pogamut.ut2004.communication.messages.ItemType;
20 import cz.cuni.amis.pogamut.ut2004.communication.messages.ItemType.Category;
21 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.ChangeWeapon;
22 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.AddInventoryMsg;
23 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.BotKilled;
24 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Item;
25 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.ItemPickedUp;
26 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
27 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Thrown;
28 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.WeaponUpdate;
29 import cz.cuni.amis.pogamut.ut2004.communication.translator.itemdescriptor.AmmoDescriptor;
30 import cz.cuni.amis.pogamut.ut2004.communication.translator.itemdescriptor.ItemDescriptor;
31 import cz.cuni.amis.pogamut.ut2004.communication.translator.itemdescriptor.WeaponDescriptor;
32 import cz.cuni.amis.utils.maps.LazyMap;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class Weaponry extends SensomotoricModule<UT2004Bot> {
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public WeaponDescriptor getDescriptorForId(UnrealId inventoryWeaponId) {
65 WeaponDescriptor desc = inventoryUnrealIdToWeaponDescriptor.get(inventoryWeaponId);
66 if (desc == null) {
67 if (log.isLoggable(Level.WARNING)) log.warning("getDescriptorForId(): There is no WeaponDescriptor for the inventory weapon id '" + inventoryWeaponId.getStringId() + "'.");
68 }
69 return desc;
70 }
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public ItemType getItemTypeForId(UnrealId inventoryWeaponId) {
85 WeaponDescriptor desc = inventoryUnrealIdToWeaponDescriptor.get(inventoryWeaponId);
86 if (desc == null) {
87 if (log.isLoggable(Level.WARNING)) log.warning("getItemTypeForId(): There is no WeaponDescriptor for the inventory weapon id '" + inventoryWeaponId.getStringId() + "'.");
88 return null;
89 }
90 return desc.getPickupType();
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public UnrealId getWeaponInventoryId(ItemType weaponType) {
108 return weaponTypeToInventoryUnrealId.get(weaponType);
109 }
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 public UnrealId getWeaponInventoryId(WeaponDescriptor weaponDescriptor) {
126 if (weaponDescriptor == null) return null;
127 if (weaponDescriptor.getPickupType() == null) {
128 if (log.isLoggable(Level.WARNING)) log.warning("getWeaponInventoryId(): WeaponDescriptor does not have PickupType assigned!");
129 return null;
130 }
131 return weaponTypeToInventoryUnrealId.get(weaponDescriptor.getPickupType());
132 }
133
134
135
136
137
138
139
140 public boolean changeWeapon(ItemType weaponType) {
141 if (weaponType == null) return false;
142 if (weaponType.getCategory() != ItemType.Category.WEAPON) return false;
143 Weapon weapon = getWeapon(weaponType);
144 return changeWeapon(getWeapon(weaponType));
145 }
146
147
148
149
150
151
152
153 public boolean changeWeapon(Weapon weapon) {
154 if (weapon == null) return false;
155 if (weapon == getCurrentWeapon()) return true;
156 if (weapon.getAmmo() <= 0) return false;
157 if (weaponsByItemType.all.get(weapon.getType()) == null) return false;
158 act.act(new ChangeWeapon().setId(weapon.getInventoryId().getStringId()));
159 return true;
160 }
161
162
163
164
165
166
167
168
169
170
171
172
173
174 public int getAmmo(ItemType ammoOrWeaponType) {
175 if (ammoOrWeaponType == null) return 0;
176 if (ammoOrWeaponType.getCategory() == ItemType.Category.WEAPON) {
177 if (hasSecondaryAmmoType(ammoOrWeaponType)) {
178 return getPrimaryWeaponAmmo(ammoOrWeaponType) + getSecondaryWeaponAmmo(ammoOrWeaponType);
179 } else {
180 return getPrimaryWeaponAmmo(ammoOrWeaponType);
181 }
182 }
183 if (ammoOrWeaponType.getCategory() == ItemType.Category.AMMO) {
184 return ammo.getAmmo(ammoOrWeaponType);
185 }
186 return 0;
187 }
188
189
190
191
192
193
194
195
196
197 public int getPrimaryWeaponAmmo(ItemType weaponType) {
198 if (weaponType == null) return 0;
199 if (weaponType.getCategory() != ItemType.Category.WEAPON) return 0;
200 return ammo.getPriAmmoForWeapon(weaponType);
201 }
202
203
204
205
206
207
208
209
210
211 public int getSecondaryWeaponAmmo(ItemType weaponType) {
212 if (weaponType == null) return 0;
213 if (weaponType.getCategory() != ItemType.Category.WEAPON) return 0;
214 return ammo.getSecAmmoForWeapon(weaponType);
215 }
216
217
218
219
220
221
222
223
224
225 public int getWeaponAmmo(ItemType weaponType) {
226 if (weaponType == null) return 0;
227 if (weaponType.getCategory() != ItemType.Category.WEAPON) return 0;
228 return ammo.getAmmoForWeapon(weaponType);
229 }
230
231
232
233
234
235
236
237
238
239
240 public boolean hasLowAmmoForWeapon(ItemType weaponType, double lowRatio) {
241 return hasPrimaryLowAmmoForWeapon(weaponType, lowRatio) || hasSecondaryLowAmmoForWeapon(weaponType, lowRatio);
242 }
243
244
245
246
247
248
249
250
251
252
253 public boolean hasSecondaryLowAmmoForWeapon(ItemType weaponType, double lowRatio) {
254 int ammo = getSecondaryWeaponAmmo(weaponType);
255 WeaponDescriptor desc = getWeaponDescriptor(weaponType);
256 return ammo / desc.getPriMaxAmount() < lowRatio;
257 }
258
259
260
261
262
263
264
265
266
267
268 public boolean hasPrimaryLowAmmoForWeapon(ItemType weaponType, double lowRatio) {
269 if (!hasSecondaryAmmoType(weaponType)) return false;
270 int ammo = getSecondaryWeaponAmmo(weaponType);
271 WeaponDescriptor desc = getWeaponDescriptor(weaponType);
272 return ammo / desc.getSecMaxAmount() < lowRatio;
273 }
274
275
276
277
278
279
280
281
282
283 public boolean hasAmmo(ItemType ammoType) {
284 if (ammoType == null) return false;
285 if (ammoType.getCategory() != ItemType.Category.AMMO) return false;
286 return ammo.getAmmo(ammoType) > 0;
287 }
288
289
290
291
292
293
294
295
296
297 public boolean hasAmmoForWeapon(ItemType weaponType) {
298 return hasWeaponAmmo(weaponType);
299 }
300
301
302
303
304
305
306
307
308
309
310 public boolean hasWeaponAmmo(ItemType weaponType) {
311 if (weaponType == null) return false;
312 if (weaponType.getCategory() != ItemType.Category.WEAPON) return false;
313 return ammo.getAmmoForWeapon(weaponType) > 0;
314 }
315
316
317
318
319
320
321
322
323
324 public boolean hasPrimaryWeaponAmmo(ItemType weaponType) {
325 if (weaponType == null) return false;
326 if (weaponType.getCategory() != ItemType.Category.WEAPON) return false;
327 return ammo.getPriAmmoForWeapon(weaponType) > 0;
328 }
329
330
331
332
333
334
335
336
337
338 public boolean hasSecondaryWeaponAmmo(ItemType weaponType) {
339 if (weaponType == null) return false;
340 if (weaponType.getCategory() != ItemType.Category.WEAPON) return false;
341 return ammo.getSecAmmoForWeapon(weaponType) > 0;
342 }
343
344
345
346
347
348
349
350
351
352 public boolean hasWeapon(ItemType weaponType) {
353 if (weaponType == null) return false;
354 if (weaponType.getCategory() != ItemType.Category.WEAPON) return false;
355 return weaponsByItemType.all.containsKey(weaponType);
356 }
357
358
359
360
361
362
363
364
365
366 public boolean hasWeapon(ItemType.Group weaponGroup) {
367 if (weaponGroup == null) return false;
368 return weaponsByGroup.all.containsKey(weaponGroup);
369 }
370
371
372
373
374
375
376
377
378
379 public boolean isLoaded(ItemType weaponType) {
380 if (weaponType == null) return false;
381 if (weaponType.getCategory() != ItemType.Category.WEAPON) return false;
382 return weaponsByItemType.allLoaded.containsKey(weaponType);
383 }
384
385
386
387
388
389
390
391
392
393 public boolean isLoaded(ItemType.Group weaponGroup) {
394 if (weaponGroup == null) return false;
395 return weaponsByGroup.allLoaded.containsKey(weaponGroup);
396 }
397
398
399
400
401
402
403
404
405
406 public boolean hasSecondaryAmmoType(ItemType weaponType) {
407 if (weaponType == null) return false;
408 if (weaponType.getCategory() != ItemType.Category.WEAPON) return false;
409 WeaponDescriptor desc = (WeaponDescriptor) itemDescriptors.getDescriptor(weaponType);
410 if (desc == null) {
411 if (log.isLoggable(Level.WARNING)) log.warning("hasSecondaryAmmoType(): There is no weapon descriptor for the item type " + weaponType + "!");
412 return false;
413 }
414 return desc.getSecAmmoItemType() != null && desc.getPriAmmoItemType() != desc.getSecAmmoItemType();
415 }
416
417
418
419
420
421
422
423
424
425 public WeaponDescriptor getWeaponDescriptor(ItemType weaponType) {
426 if (weaponType == null) return null;
427 if (weaponType.getCategory() != ItemType.Category.WEAPON) return null;
428 WeaponDescriptor desc = (WeaponDescriptor) itemDescriptors.getDescriptor(weaponType);
429 if (desc == null) {
430 if (log.isLoggable(Level.WARNING)) log.warning("getWeaponDescriptor(): There is no weapon descriptor for the item type " + weaponType + "!");
431 }
432 return desc;
433 }
434
435
436
437
438
439
440
441
442
443
444 public Weapon getCurrentWeapon() {
445 if (self == null) {
446 return null;
447 }
448 if (self.getWeapon() == null) {
449 return null;
450 }
451 WeaponDescriptor desc = inventoryUnrealIdToWeaponDescriptor.get(UnrealId.get(self.getWeapon()));
452 if (desc == null) {
453 if (self.getWeapon().equalsIgnoreCase(AgentInfo.NONE_WEAPON_ID)) return null;
454 if (log.isLoggable(Level.WARNING)) log.warning("getCurrentWeapon(): There is no weapon descriptor for current bot's weapon of id: '" + self.getWeapon() + "'");
455 return null;
456 }
457 return weaponsByItemType.all.get(desc.getPickupType());
458 }
459
460
461
462
463
464
465
466
467
468
469 public int getCurrentAmmo() {
470 if (getCurrentWeapon() == null) return 0;
471 if (getCurrentWeapon().hasSecondaryAmmoType()) {
472 return getCurrentPrimaryAmmo() + getCurrentAlternateAmmo();
473 } else {
474 return getCurrentPrimaryAmmo();
475 }
476 }
477
478
479
480
481
482
483
484
485
486 public int getCurrentPrimaryAmmo() {
487
488 if (self == null) {
489 return 0;
490 }
491 return self.getPrimaryAmmo();
492 }
493
494
495
496
497
498
499
500
501
502
503 public int getCurrentAlternateAmmo() {
504 if (self == null) {
505 return 0;
506 }
507 if (self.getWeapon() == null) {
508 return 0;
509 }
510 WeaponDescriptor weaponDesc = inventoryUnrealIdToWeaponDescriptor.get(UnrealId.get(self.getWeapon()));
511 if (weaponDesc == null) {
512 if (self.getWeapon().equals(AgentInfo.NONE_WEAPON_ID)) return 0;
513 if (log.isLoggable(Level.WARNING)) log.warning("getCurrentAlternateAmmo(): There is no weapon descriptor for current bot's weapon of id: '" + self.getWeapon() + "'");
514 return 0;
515 }
516 if (weaponDesc.getSecAmmoItemType() != null) {
517 return self.getSecondaryAmmo();
518 } else {
519 return self.getPrimaryAmmo();
520 }
521 }
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536 public Map<ItemType, Weapon> getWeapons() {
537 return Collections.unmodifiableMap(weaponsByItemType.all);
538 }
539
540
541
542
543
544
545
546
547 public Weapon getWeapon(ItemType weaponType) {
548 if (weaponType == null) return null;
549 if (weaponType.getCategory() != ItemType.Category.WEAPON) return null;
550 return weaponsByItemType.all.get(weaponType);
551 }
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570 public Map<ItemType, Weapon> getLoadedWeapons() {
571 return Collections.unmodifiableMap(weaponsByItemType.allLoaded);
572 }
573
574
575
576
577
578
579
580
581
582
583
584
585 public Map<ItemType, Weapon> getMeleeWeapons() {
586 return Collections.unmodifiableMap(weaponsByItemType.allMelee);
587 }
588
589
590
591
592
593
594
595
596
597
598
599
600 public Map<ItemType, Weapon> getRangedWeapons() {
601 return Collections.unmodifiableMap(weaponsByItemType.allRanged);
602 }
603
604
605
606
607
608
609
610
611
612
613
614
615 public Map<ItemType, Weapon> getLoadedMeleeWeapons() {
616 return Collections.unmodifiableMap(weaponsByItemType.allLoadedMelee);
617 }
618
619
620
621
622
623
624
625
626
627
628
629
630 public Map<ItemType, Weapon> getLoadedRangedWeapons() {
631 return Collections.unmodifiableMap(weaponsByItemType.allLoadedRanged);
632 }
633
634
635
636
637
638
639
640
641
642 public Map<ItemType, Integer> getAmmos() {
643 return Collections.unmodifiableMap(ammo.ammo);
644 }
645
646
647
648
649
650
651
652
653
654
655
656 public boolean hasLoadedWeapon() {
657
658 return !getLoadedWeapons().isEmpty();
659 }
660
661
662
663
664
665
666
667
668
669 public boolean hasLoadedRangedWeapon() {
670
671 return !getLoadedRangedWeapons().isEmpty();
672 }
673
674
675
676
677
678
679
680
681
682
683
684 public boolean hasLoadedMeleeWeapon() {
685
686 return !getLoadedMeleeWeapons().isEmpty();
687 }
688
689
690
691
692
693
694 public boolean hasLoadedWeapon(ItemType weapon) {
695 return hasPrimaryLoadedWeapon(weapon) || hasSecondaryLoadedWeapon(weapon);
696 }
697
698
699
700
701
702
703 public boolean hasPrimaryLoadedWeapon(ItemType weapon) {
704 Weapon w = getWeapon(weapon);
705 if (w == null) return false;
706 return w.getPrimaryAmmo() > 0;
707 }
708
709
710
711
712
713
714 public boolean hasSecondaryLoadedWeapon(ItemType weapon) {
715 Weapon w = getWeapon(weapon);
716 if (w == null) return false;
717 return w.getSecondaryAmmo() > 0;
718 }
719
720
721
722
723
724
725
726 public ItemType getWeaponForAmmo(ItemType priOrSecAmmoType) {
727 for (ItemType weaponType : Category.WEAPON.getTypes()) {
728 WeaponDescriptor desc = (WeaponDescriptor)itemDescriptors.getDescriptor(weaponType);
729 if (desc == null) continue;
730 if (desc.getPriAmmoItemType() == priOrSecAmmoType) return weaponType;
731 if (desc.getSecAmmoItemType() == priOrSecAmmoType) return weaponType;
732 }
733 return null;
734 }
735
736
737
738
739
740
741 public ItemType getPrimaryWeaponAmmoType(ItemType weaponType) {
742 WeaponDescriptor desc = (WeaponDescriptor)itemDescriptors.getDescriptor(weaponType);
743 if (desc == null) return null;
744 return desc.getPriAmmoItemType();
745 }
746
747
748
749
750
751
752 public ItemType getSecondaryWeaponAmmoType(ItemType weaponType) {
753 WeaponDescriptor desc = (WeaponDescriptor)itemDescriptors.getDescriptor(weaponType);
754 if (desc == null) return null;
755 return desc.getSecAmmoItemType();
756 }
757
758
759
760
761
762
763
764
765
766
767
768 private class Ammunition {
769
770
771
772
773 private LazyMap<ItemType, Integer> ammo = new LazyMap<ItemType, Integer>() {
774 @Override
775 protected Integer create(ItemType key) {
776 return 0;
777 }
778 };
779
780
781
782
783
784
785 public int getAmmo(ItemType ammoType) {
786 if (ammoType == null) return 0;
787 if (ammoType.getCategory() != ItemType.Category.AMMO) return 0;
788 return ammo.get(ammoType);
789 }
790
791
792
793
794
795
796 public int getPriAmmoForWeapon(ItemType weapon) {
797 if (weapon == null) return 0;
798 if (weapon.getCategory() != ItemType.Category.WEAPON) return 0;
799 WeaponDescriptor desc = (WeaponDescriptor)itemDescriptors.getDescriptor(weapon);
800 if (desc == null) {
801 if (log.isLoggable(Level.WARNING)) log.warning("Ammunition.getPriAmmoForWeapon(): There is no WeaponDescriptor for the item type " + weapon + "!");
802 return 0;
803 }
804 return getAmmo(desc.getPriAmmoItemType());
805 }
806
807
808
809
810
811
812
813 public int getSecAmmoForWeapon(ItemType weaponType) {
814 if (weaponType == null) return 0;
815 if (weaponType.getCategory() != ItemType.Category.WEAPON) return 0;
816 WeaponDescriptor desc = (WeaponDescriptor)itemDescriptors.getDescriptor(weaponType);
817 if (desc == null) {
818 if (log.isLoggable(Level.WARNING)) log.warning("Ammunition.getSecAmmoForWeapon(): There is no WeaponDescriptor for the item type " + weaponType + "!");
819 return 0;
820 }
821 if (desc.getSecAmmoItemType() == null) return getPriAmmoForWeapon(weaponType);
822 return getAmmo(desc.getSecAmmoItemType());
823 }
824
825
826
827
828
829
830 public int getAmmoForWeapon(ItemType weaponType) {
831 if (weaponType == null) return 0;
832 if (weaponType.getCategory() != ItemType.Category.WEAPON) return 0;
833 WeaponDescriptor desc = (WeaponDescriptor) itemDescriptors.getDescriptor(weaponType);
834 if (desc == null) {
835 if (log.isLoggable(Level.WARNING)) log.warning("Ammunition.getAmmoForWeapon(): There is no WeaponDescriptor for the item type " + weaponType + "!");
836 return 0;
837 }
838 if (desc.getSecAmmoItemType() != null && desc.getPriAmmoItemType()!= desc.getSecAmmoItemType()) {
839 return getPriAmmoForWeapon(weaponType) + getSecAmmoForWeapon(weaponType);
840 } else {
841 return getPriAmmoForWeapon(weaponType);
842 }
843 }
844
845
846
847
848
849 public void itemPickedUp(ItemPickedUp pickedUp) {
850 if (pickedUp == null) return;
851 ItemDescriptor descriptor = itemDescriptors.getDescriptor(pickedUp.getType());
852 if (descriptor == null) {
853 if (log.isLoggable(Level.WARNING)) log.warning("Ammunition.itemPickedUp(): There is no ItemDescriptor for the item type " + pickedUp.getType() + "!");
854 return;
855 }
856
857 if (pickedUp.getDescriptor().getPickupType() == ItemType.REDEEMER
858 || pickedUp.getDescriptor().getPickupType() == ItemType.REDEEMER_AMMO
859 || pickedUp.getDescriptor().getPickupType() == ItemType.ION_PAINTER
860 || pickedUp.getDescriptor().getPickupType() == ItemType.ION_PAINTER_AMMO
861 )
862
863 {
864
865 if (descriptor.getItemCategory() == Category.AMMO) {
866 if (ammo.get(pickedUp.getType()) <= 0) {
867 ammo.put(pickedUp.getType(), 1);
868 }
869 } else
870 if (descriptor.getItemCategory() == Category.WEAPON) {
871 WeaponDescriptor desc = (WeaponDescriptor)descriptor;
872 if (ammo.get(desc.getPriAmmoItemType()) == 0) {
873 ammo.put(desc.getPriAmmoItemType(), 1);
874 }
875 }
876 return;
877 }
878
879 if (descriptor.getItemCategory() == Category.AMMO) {
880 AmmoDescriptor desc = (AmmoDescriptor)descriptor;
881 int current = getAmmo(pickedUp.getType());
882 if (current + pickedUp.getAmount() > desc.getPriMaxAmount()) {
883 ammo.put(pickedUp.getType(), desc.getPriMaxAmount());
884 } else {
885 ammo.put(pickedUp.getType(), current + pickedUp.getAmount());
886 }
887 } else
888 if (descriptor.getItemCategory() == Category.WEAPON) {
889 WeaponDescriptor desc = (WeaponDescriptor)descriptor;
890
891 if (desc.getPriAmmoItemType() != null) {
892 int priAmmo = ammo.get(desc.getPriAmmoItemType());
893
894 int priWeaponAmmoPlus = pickedUp.getAmount();
895 if (priAmmo + priWeaponAmmoPlus <= desc.getPriMaxAmount()) {
896 ammo.put(desc.getPriAmmoItemType(), priAmmo + priWeaponAmmoPlus);
897 } else {
898 ammo.put(desc.getPriAmmoItemType(), desc.getPriMaxAmount());
899 }
900 }
901
902 if (desc.getSecAmmoItemType() != null && desc.getSecAmmoItemType() != desc.getPriAmmoItemType()) {
903 int secAmmo = ammo.get(desc.getSecAmmoItemType());
904 int secWeaponAmmoPlus = pickedUp.getAmountSec();
905 if (secAmmo + secWeaponAmmoPlus <= desc.getSecMaxAmount()) {
906 ammo.put(desc.getSecAmmoItemType(), secAmmo + secWeaponAmmoPlus);
907 } else {
908 ammo.put(desc.getSecAmmoItemType(), desc.getSecMaxAmount());
909 }
910 }
911 }
912 }
913
914
915
916
917
918
919
920 public void weaponUpdate(ItemType ammoType, int amount) {
921
922
923 if (ammoType == null) return;
924 if (ammoType.getCategory() != ItemType.Category.AMMO) {
925 if (log.isLoggable(Level.SEVERE)) log.severe("Ammunition.weaponUpdate: Can't update weapon ammo, unknown ammo type=" + ammoType.getName() + ", category=" + ammoType.getCategory() + ", group=" + ammoType.getGroup());
926 return;
927 }
928 ammo.put(ammoType, amount);
929 }
930
931
932
933
934 public void botKilled() {
935 ammo.clear();
936 }
937
938
939
940
941 public void updateWeaponAmmo(Weapon weapon) {
942 if (weapon == null) return;
943 weapon.primaryAmmo = getAmmo(weapon.getDescriptor().getPriAmmoItemType());
944 if (weapon.getDescriptor().getSecAmmoItemType() != null) {
945 weapon.secondaryAmmo = getAmmo(weapon.getDescriptor().getSecAmmoItemType());
946 }
947 weaponsByGroup.ammoChanged(weapon.getGroup());
948 weaponsByItemType.ammoChanged(weapon.getType());
949 weaponsById.ammoChanged(weapon.getInventoryId());
950 }
951 }
952
953 private Ammunition ammo = new Ammunition();
954
955
956
957
958
959
960 private class WeaponsByKey<KEY> {
961
962 private HashMap<KEY, Weapon> all = new HashMap<KEY, Weapon>();
963
964 private HashMap<KEY, Weapon> allLoaded = new HashMap<KEY, Weapon>();
965
966 private HashMap<KEY, Weapon> allMelee = new HashMap<KEY, Weapon>();
967
968 private HashMap<KEY, Weapon> allRanged = new HashMap<KEY, Weapon>();
969
970 private HashMap<KEY, Weapon> allLoadedMelee = new HashMap<KEY, Weapon>();
971
972 private HashMap<KEY, Weapon> allLoadedRanged = new HashMap<KEY, Weapon>();
973
974
975
976
977
978
979
980 public void add(KEY key, Weapon inv) {
981 if (key == null || inv == null) return;
982 if (inv.getDescriptor() == null) {
983 if (log.isLoggable(Level.WARNING)) log.warning("WeaponsByKey.add(): Can't add weapon " + inv.getType() + " that has associated weapon descriptor == null!");
984 return;
985 }
986 if (inv.getDescriptor() instanceof WeaponDescriptor) {
987 WeaponDescriptor desc = inv.getDescriptor();
988 all.put(key, inv);
989 if (desc.isMelee()) {
990 allMelee.put(key, inv);
991 if (inv.getAmmo() > 0) {
992 allLoadedMelee.put(key, inv);
993 allLoaded.put(key, inv);
994 }
995 } else {
996 allRanged.put(key, inv);
997 if (inv.getAmmo() > 0) {
998 allLoadedRanged.put(key, inv);
999 allLoaded.put(key, inv);
1000 }
1001 }
1002 }
1003 }
1004
1005
1006
1007
1008 public void remove(KEY key) {
1009 all.remove(key);
1010 allLoaded.remove(key);
1011 allMelee.remove(key);
1012 allRanged.remove(key);
1013 allLoadedMelee.remove(key);
1014 allLoadedRanged.remove(key);
1015 }
1016
1017
1018
1019
1020
1021 public void ammoChanged(KEY key) {
1022 if (key == null) return;
1023 Weapon weapon = all.get(key);
1024 if (weapon == null) {
1025
1026 return;
1027 }
1028 if (weapon.getAmmo() > 0) {
1029 if (!allLoaded.containsKey(key)) {
1030
1031 WeaponDescriptor desc = (weapon.getDescriptor());
1032 allLoaded.put(key, weapon);
1033 if (desc.isMelee()) {
1034 allLoadedMelee.put(key, weapon);
1035 } else {
1036 allLoadedRanged.put(key, weapon);
1037 }
1038 }
1039 } else {
1040
1041 if (allLoaded.containsKey(key)) {
1042
1043 allLoaded.remove(key);
1044 allLoadedMelee.remove(key);
1045 allLoadedRanged.remove(key);
1046 }
1047 }
1048 }
1049
1050
1051
1052
1053 public void botKilled() {
1054 all.clear();
1055 allLoaded.clear();
1056 allLoadedMelee.clear();
1057 allLoadedRanged.clear();
1058 allMelee.clear();
1059 allRanged.clear();
1060 }
1061
1062 }
1063
1064 WeaponsByKey<ItemType.Group> weaponsByGroup = new WeaponsByKey<ItemType.Group>();
1065
1066 WeaponsByKey<ItemType> weaponsByItemType = new WeaponsByKey<ItemType>();
1067
1068 WeaponsByKey<UnrealId> weaponsById = new WeaponsByKey<UnrealId>();
1069
1070
1071
1072 private Map<ItemType, UnrealId> weaponTypeToInventoryUnrealId = new HashMap<ItemType, UnrealId>();
1073 private Map<UnrealId, WeaponDescriptor> inventoryUnrealIdToWeaponDescriptor = new HashMap<UnrealId, WeaponDescriptor>();
1074
1075
1076
1077
1078
1079
1080 private class AddInventoryMsgListener implements IWorldEventListener<AddInventoryMsg> {
1081
1082 @Override
1083 public void notify(AddInventoryMsg event) {
1084 if (event == null) return;
1085 if (event.getPickupType() == null) return;
1086 if (event.getPickupType().getCategory() != ItemType.Category.WEAPON) return;
1087
1088
1089
1090
1091 if (event.getPickupType() == ItemType.REDEEMER) {
1092 log.info("REDEEMER!");
1093 }
1094
1095 Weapon weapon = new Weapon(event, ammo.getPriAmmoForWeapon(event.getPickupType()), ammo.getSecAmmoForWeapon(event.getPickupType()));
1096
1097 if (weapon.getDescriptor() == null) {
1098 if (log.isLoggable(Level.SEVERE)) log.severe("AddInventoryMsgListener.notify(): There is no weapon descriptor for " + weapon.getType() + "!!! The newly gained weapon is not added to the Weaponry!");
1099 return;
1100 }
1101
1102
1103 weaponsByGroup.add(event.getPickupType().getGroup(), weapon);
1104 weaponsByItemType.add(event.getPickupType(), weapon);
1105 weaponsById.add(event.getId(), weapon);
1106
1107 weaponTypeToInventoryUnrealId.put(event.getPickupType(), event.getId());
1108 inventoryUnrealIdToWeaponDescriptor.put(event.getId(), (WeaponDescriptor) event.getDescriptor());
1109 }
1110
1111
1112
1113
1114
1115 public AddInventoryMsgListener(IWorldView worldView) {
1116 worldView.addEventListener(AddInventoryMsg.class, this);
1117 }
1118 }
1119
1120 AddInventoryMsgListener addInventoryMsgListener;
1121
1122
1123
1124
1125
1126
1127
1128 private class ItemPickedUpListener implements IWorldEventListener<ItemPickedUp> {
1129
1130 @Override
1131 public void notify(ItemPickedUp event) {
1132 if (event == null) return;
1133 if (event.getType() == null) return;
1134 if (event.getType().getCategory() == Category.AMMO || event.getType().getCategory() == Category.WEAPON) {
1135 ammo.itemPickedUp(event);
1136 Weapon weapon;
1137 if (event.getType().getCategory() == Category.AMMO) {
1138 ItemType weaponType = itemDescriptors.getWeaponForAmmo(event.getType());
1139 if (weaponType == null) {
1140 if (log.isLoggable(Level.WARNING)) log.warning("ItemPickedUpListener.notify(): There is no weapon for the ammo " + event.getType() + ", the weapon probably can not be found in this map.");
1141 return;
1142 }
1143 weapon = weaponsByItemType.all.get(weaponType);
1144 } else {
1145
1146 ItemType weaponType = event.getType();
1147 weapon = weaponsByItemType.all.get(weaponType);
1148 }
1149 if (weapon != null) {
1150 ammo.updateWeaponAmmo(weapon);
1151 }
1152 }
1153 }
1154
1155
1156
1157
1158
1159 public ItemPickedUpListener(IWorldView worldView) {
1160 worldView.addEventListener(ItemPickedUp.class, this);
1161 }
1162 }
1163
1164 ItemPickedUpListener itemPickedUpListener;
1165
1166
1167
1168
1169
1170
1171
1172
1173 private class WeaponUpdateListener implements IWorldEventListener<WeaponUpdate> {
1174
1175 @Override
1176 public void notify(WeaponUpdate event) {
1177 if (event == null) return;
1178 if (event.getInventoryType() == null) return;
1179 WeaponDescriptor weaponDesc = (WeaponDescriptor)itemDescriptors.getDescriptor(event.getInventoryType());
1180 if (weaponDesc == null) {
1181 Weapon weapon = weaponsById.all.get(event.getId());
1182 if (weapon != null) {
1183 weaponDesc = weapon.getDescriptor();
1184 }
1185 }
1186 if (weaponDesc == null) {
1187 if (log.isLoggable(Level.WARNING)) log.warning("WeaponUpdateListener.notify(): There is no weapon descriptor for the weapon for the event: " + event);
1188 return;
1189 }
1190 if (weaponDesc.getPriAmmoItemType() != null) {
1191 ammo.weaponUpdate(weaponDesc.getPriAmmoItemType(), event.getPrimaryAmmo());
1192 }
1193 if (weaponDesc.getSecAmmoItemType() != null && weaponDesc.getSecAmmoItemType() != weaponDesc.getPriAmmoItemType()) {
1194 ammo.weaponUpdate(weaponDesc.getSecAmmoItemType(), event.getSecondaryAmmo());
1195 }
1196
1197 Weapon weapon = weaponsByItemType.all.get(weaponDesc.getPickupType());
1198 if (weapon != null) {
1199 ammo.updateWeaponAmmo(weapon);
1200 }
1201 }
1202
1203
1204
1205
1206
1207 public WeaponUpdateListener(IWorldView worldView) {
1208 worldView.addEventListener(WeaponUpdate.class, this);
1209 }
1210 }
1211
1212 WeaponUpdateListener weaponUpdateListener;
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222 private class SelfUpdateListener implements IWorldObjectEventListener<Self, WorldObjectUpdatedEvent<Self>> {
1223
1224 public void notify(WorldObjectUpdatedEvent<Self> event) {
1225 if (event == null) return;
1226
1227
1228 if (self == null) {
1229 self = event.getObject();
1230 }
1231
1232 Weapon weaponToUpdate = getCurrentWeapon();
1233 if (weaponToUpdate != null) {
1234 WeaponDescriptor weaponDesc = weaponToUpdate.getDescriptor();
1235 if (weaponDesc == null) {
1236 if (log.isLoggable(Level.WARNING)) log.warning("SelfUpdateListener.notify(): There is no weapon descriptor for the weapon " + weaponToUpdate);
1237 return;
1238 }
1239 if (weaponDesc.getPriAmmoItemType() != null) {
1240 ammo.weaponUpdate(weaponDesc.getPriAmmoItemType(), self.getPrimaryAmmo());
1241 }
1242 if (weaponDesc.getSecAmmoItemType() != null && weaponDesc.getSecAmmoItemType() != weaponDesc.getPriAmmoItemType()) {
1243 ammo.weaponUpdate(weaponDesc.getSecAmmoItemType(), self.getSecondaryAmmo());
1244 }
1245 ammo.updateWeaponAmmo(weaponToUpdate);
1246 }
1247 }
1248
1249
1250
1251
1252
1253 public SelfUpdateListener(IWorldView worldView) {
1254 worldView.addObjectListener(Self.class, WorldObjectUpdatedEvent.class, this);
1255 }
1256 }
1257
1258
1259 SelfUpdateListener selfUpdateListener;
1260
1261
1262
1263
1264
1265
1266
1267 private class ThrownListener implements IWorldEventListener<Thrown> {
1268
1269 @Override
1270 public void notify(Thrown event) {
1271 WeaponDescriptor desc = inventoryUnrealIdToWeaponDescriptor.get(event.getId());
1272 if (desc == null) {
1273 if (log.isLoggable(Level.WARNING)) log.warning("ThrownListener.notify(): There is no known weapon descriptor for id " + event.getId() + " inside Weaponary.");
1274 return;
1275 }
1276 ItemType weaponType = desc.getPickupType();
1277 weaponsByGroup.remove(weaponType.getGroup());
1278 weaponsByItemType.remove(weaponType);
1279 }
1280
1281
1282
1283
1284
1285 public ThrownListener(IWorldView worldView) {
1286 worldView.addEventListener(Thrown.class, this);
1287 }
1288 }
1289
1290 ThrownListener thrownListener;
1291
1292
1293
1294
1295
1296
1297
1298 private class BotKilledListener implements IWorldEventListener<BotKilled> {
1299
1300 @Override
1301 public void notify(BotKilled event) {
1302 ammo.botKilled();
1303 weaponsByGroup.botKilled();
1304 weaponsByItemType.botKilled();
1305 weaponsById.botKilled();
1306 weaponTypeToInventoryUnrealId.clear();
1307 inventoryUnrealIdToWeaponDescriptor.clear();
1308 }
1309
1310
1311
1312
1313
1314 public BotKilledListener(IWorldView worldView) {
1315 worldView.addEventListener(BotKilled.class, this);
1316 }
1317
1318 }
1319
1320 BotKilledListener botKilledListener;
1321
1322
1323
1324 private ItemDescriptors itemDescriptors;
1325
1326
1327
1328 private Self self = null;
1329
1330
1331
1332
1333
1334 public Weaponry(UT2004Bot bot) {
1335 this(bot, new ItemDescriptors(bot));
1336 }
1337
1338
1339
1340
1341
1342
1343
1344 public Weaponry(UT2004Bot bot, ItemDescriptors itemDescriptors) {
1345 this(bot, itemDescriptors, null);
1346 }
1347
1348
1349
1350
1351
1352
1353
1354
1355 public Weaponry(UT2004Bot bot, ItemDescriptors descriptors, LogCategory moduleLog) {
1356 super(bot);
1357
1358 this.itemDescriptors = descriptors;
1359
1360 if (this.itemDescriptors == null) {
1361 this.itemDescriptors = new ItemDescriptors(bot, moduleLog);
1362 }
1363
1364
1365 addInventoryMsgListener = new AddInventoryMsgListener(worldView);
1366 itemPickedUpListener = new ItemPickedUpListener(worldView);
1367 weaponUpdateListener = new WeaponUpdateListener(worldView);
1368 selfUpdateListener = new SelfUpdateListener(worldView);
1369 thrownListener = new ThrownListener(worldView);
1370 botKilledListener = new BotKilledListener(worldView);
1371
1372 cleanUp();
1373 }
1374
1375 @Override
1376 protected void cleanUp() {
1377 super.cleanUp();
1378
1379 ammo.botKilled();
1380 weaponsByGroup.botKilled();
1381 weaponsByItemType.botKilled();
1382 weaponsById.botKilled();
1383 weaponTypeToInventoryUnrealId.clear();
1384 inventoryUnrealIdToWeaponDescriptor.clear();
1385 }
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395 public int getMaxAmmo(ItemType ammoType) {
1396 if (ammoType == null) return 0;
1397 WeaponDescriptor weapon = getWeaponDescriptor( getWeaponForAmmo(ammoType) );
1398 if (weapon == null) {
1399 if (log.isLoggable(Level.WARNING)) log.warning("There is no known weapon descriptor for item type " + ammoType + " inside Weaponary.");
1400 return 0;
1401 }
1402 if ( weapon.getPriAmmoItemType() == ammoType ) {
1403 return weapon.getPriMaxAmount();
1404 } else if ( weapon.getSecAmmoItemType() == ammoType ) {
1405 return weapon.getSecMaxAmount();
1406 } else {
1407 return 0;
1408 }
1409 }
1410
1411 }