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 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
858 if (descriptor.getItemCategory() == Category.AMMO) {
859 AmmoDescriptor desc = (AmmoDescriptor)descriptor;
860 int current = getAmmo(pickedUp.getType());
861 if (current + pickedUp.getAmount() > desc.getPriMaxAmount()) {
862 ammo.put(pickedUp.getType(), desc.getPriMaxAmount());
863 } else {
864 ammo.put(pickedUp.getType(), current + pickedUp.getAmount());
865 }
866 } else
867 if (descriptor.getItemCategory() == Category.WEAPON) {
868 WeaponDescriptor desc = (WeaponDescriptor)descriptor;
869
870 if (desc.getPriAmmoItemType() != null) {
871 int priAmmo = ammo.get(desc.getPriAmmoItemType());
872
873 int priWeaponAmmoPlus = pickedUp.getAmount();
874 if (priAmmo + priWeaponAmmoPlus <= desc.getPriMaxAmount()) {
875 ammo.put(desc.getPriAmmoItemType(), priAmmo + priWeaponAmmoPlus);
876 } else {
877 ammo.put(desc.getPriAmmoItemType(), desc.getPriMaxAmount());
878 }
879 }
880
881 if (desc.getSecAmmoItemType() != null && desc.getSecAmmoItemType() != desc.getPriAmmoItemType()) {
882 int secAmmo = ammo.get(desc.getSecAmmoItemType());
883 int secWeaponAmmoPlus = pickedUp.getAmountSec();
884 if (secAmmo + secWeaponAmmoPlus <= desc.getSecMaxAmount()) {
885 ammo.put(desc.getSecAmmoItemType(), secAmmo + secWeaponAmmoPlus);
886 } else {
887 ammo.put(desc.getSecAmmoItemType(), desc.getSecMaxAmount());
888 }
889 }
890 }
891 }
892
893
894
895
896
897
898
899 public void weaponUpdate(ItemType ammoType, int amount) {
900
901
902 if (ammoType == null) return;
903 if (ammoType.getCategory() != ItemType.Category.AMMO) {
904 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());
905 return;
906 }
907 ammo.put(ammoType, amount);
908 }
909
910
911
912
913 public void botKilled() {
914 ammo.clear();
915 }
916
917
918
919
920 public void updateWeaponAmmo(Weapon weapon) {
921 if (weapon == null) return;
922 weapon.primaryAmmo = getAmmo(weapon.getDescriptor().getPriAmmoItemType());
923 if (weapon.getDescriptor().getSecAmmoItemType() != null) {
924 weapon.secondaryAmmo = getAmmo(weapon.getDescriptor().getSecAmmoItemType());
925 }
926 weaponsByGroup.ammoChanged(weapon.getGroup());
927 weaponsByItemType.ammoChanged(weapon.getType());
928 weaponsById.ammoChanged(weapon.getInventoryId());
929 }
930 }
931
932 Ammunition ammo = new Ammunition();
933
934
935
936
937
938
939 private class WeaponsByKey<KEY> {
940
941 private HashMap<KEY, Weapon> all = new HashMap<KEY, Weapon>();
942
943 private HashMap<KEY, Weapon> allLoaded = new HashMap<KEY, Weapon>();
944
945 private HashMap<KEY, Weapon> allMelee = new HashMap<KEY, Weapon>();
946
947 private HashMap<KEY, Weapon> allRanged = new HashMap<KEY, Weapon>();
948
949 private HashMap<KEY, Weapon> allLoadedMelee = new HashMap<KEY, Weapon>();
950
951 private HashMap<KEY, Weapon> allLoadedRanged = new HashMap<KEY, Weapon>();
952
953
954
955
956
957
958
959 public void add(KEY key, Weapon inv) {
960 if (key == null || inv == null) return;
961 if (inv.getDescriptor() == null) {
962 if (log.isLoggable(Level.WARNING)) log.warning("WeaponsByKey.add(): Can't add weapon " + inv.getType() + " that has associated weapon descriptor == null!");
963 return;
964 }
965 if (inv.getDescriptor() instanceof WeaponDescriptor) {
966 WeaponDescriptor desc = inv.getDescriptor();
967 all.put(key, inv);
968 if (desc.isMelee()) {
969 allMelee.put(key, inv);
970 if (inv.getAmmo() > 0) {
971 allLoadedMelee.put(key, inv);
972 allLoaded.put(key, inv);
973 }
974 } else {
975 allRanged.put(key, inv);
976 if (inv.getAmmo() > 0) {
977 allLoadedRanged.put(key, inv);
978 allLoaded.put(key, inv);
979 }
980 }
981 }
982 }
983
984
985
986
987 public void remove(KEY key) {
988 all.remove(key);
989 allLoaded.remove(key);
990 allMelee.remove(key);
991 allRanged.remove(key);
992 allLoadedMelee.remove(key);
993 allLoadedRanged.remove(key);
994 }
995
996
997
998
999
1000 public void ammoChanged(KEY key) {
1001 if (key == null) return;
1002 Weapon weapon = all.get(key);
1003 if (weapon == null) {
1004
1005 return;
1006 }
1007 if (weapon.getAmmo() > 0) {
1008 if (!allLoaded.containsKey(key)) {
1009
1010 WeaponDescriptor desc = (weapon.getDescriptor());
1011 allLoaded.put(key, weapon);
1012 if (desc.isMelee()) {
1013 allLoadedMelee.put(key, weapon);
1014 } else {
1015 allLoadedRanged.put(key, weapon);
1016 }
1017 }
1018 } else {
1019
1020 if (allLoaded.containsKey(key)) {
1021
1022 allLoaded.remove(key);
1023 allLoadedMelee.remove(key);
1024 allLoadedRanged.remove(key);
1025 }
1026 }
1027 }
1028
1029
1030
1031
1032 public void botKilled() {
1033 all.clear();
1034 allLoaded.clear();
1035 allLoadedMelee.clear();
1036 allLoadedRanged.clear();
1037 allMelee.clear();
1038 allRanged.clear();
1039 }
1040
1041 }
1042
1043 WeaponsByKey<ItemType.Group> weaponsByGroup = new WeaponsByKey<ItemType.Group>();
1044
1045 WeaponsByKey<ItemType> weaponsByItemType = new WeaponsByKey<ItemType>();
1046
1047 WeaponsByKey<UnrealId> weaponsById = new WeaponsByKey<UnrealId>();
1048
1049
1050
1051 private Map<ItemType, UnrealId> weaponTypeToInventoryUnrealId = new HashMap<ItemType, UnrealId>();
1052 private Map<UnrealId, WeaponDescriptor> inventoryUnrealIdToWeaponDescriptor = new HashMap<UnrealId, WeaponDescriptor>();
1053
1054
1055
1056
1057
1058
1059 private class AddInventoryMsgListener implements IWorldEventListener<AddInventoryMsg> {
1060
1061 @Override
1062 public void notify(AddInventoryMsg event) {
1063 if (event == null) return;
1064 if (event.getPickupType() == null) return;
1065 if (event.getPickupType().getCategory() != ItemType.Category.WEAPON) return;
1066
1067
1068
1069
1070
1071
1072
1073
1074 Weapon weapon = new Weapon(event, ammo.getPriAmmoForWeapon(event.getPickupType()), ammo.getSecAmmoForWeapon(event.getPickupType()));
1075
1076 if (weapon.getDescriptor() == null) {
1077 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!");
1078 return;
1079 }
1080
1081
1082 weaponsByGroup.add(event.getPickupType().getGroup(), weapon);
1083 weaponsByItemType.add(event.getPickupType(), weapon);
1084 weaponsById.add(event.getId(), weapon);
1085
1086 weaponTypeToInventoryUnrealId.put(event.getPickupType(), event.getId());
1087 inventoryUnrealIdToWeaponDescriptor.put(event.getId(), (WeaponDescriptor) event.getDescriptor());
1088 }
1089
1090
1091
1092
1093
1094 public AddInventoryMsgListener(IWorldView worldView) {
1095 worldView.addEventListener(AddInventoryMsg.class, this);
1096 }
1097 }
1098
1099 AddInventoryMsgListener addInventoryMsgListener;
1100
1101
1102
1103
1104
1105
1106
1107 private class ItemPickedUpListener implements IWorldEventListener<ItemPickedUp> {
1108
1109 @Override
1110 public void notify(ItemPickedUp event) {
1111 if (event == null) return;
1112 if (event.getType() == null) return;
1113 if (event.getType().getCategory() == Category.AMMO || event.getType().getCategory() == Category.WEAPON) {
1114 ammo.itemPickedUp(event);
1115 Weapon weapon;
1116 if (event.getType().getCategory() == Category.AMMO) {
1117 ItemType weaponType = itemDescriptors.getWeaponForAmmo(event.getType());
1118 if (weaponType == null) {
1119 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.");
1120 return;
1121 }
1122 weapon = weaponsByItemType.all.get(weaponType);
1123 } else {
1124
1125 ItemType weaponType = event.getType();
1126 weapon = weaponsByItemType.all.get(weaponType);
1127 }
1128 if (weapon != null) {
1129 ammo.updateWeaponAmmo(weapon);
1130 }
1131 }
1132 }
1133
1134
1135
1136
1137
1138 public ItemPickedUpListener(IWorldView worldView) {
1139 worldView.addEventListener(ItemPickedUp.class, this);
1140 }
1141 }
1142
1143 ItemPickedUpListener itemPickedUpListener;
1144
1145
1146
1147
1148
1149
1150
1151
1152 private class WeaponUpdateListener implements IWorldEventListener<WeaponUpdate> {
1153
1154 @Override
1155 public void notify(WeaponUpdate event) {
1156 if (event == null) return;
1157 if (event.getInventoryType() == null) return;
1158 WeaponDescriptor weaponDesc = (WeaponDescriptor)itemDescriptors.getDescriptor(event.getInventoryType());
1159 if (weaponDesc == null) {
1160 Weapon weapon = weaponsById.all.get(event.getId());
1161 if (weapon != null) {
1162 weaponDesc = weapon.getDescriptor();
1163 }
1164 }
1165 if (weaponDesc == null) {
1166 if (log.isLoggable(Level.WARNING)) log.warning("WeaponUpdateListener.notify(): There is no weapon descriptor for the weapon for the event: " + event);
1167 return;
1168 }
1169 if (weaponDesc.getPriAmmoItemType() != null) {
1170 ammo.weaponUpdate(weaponDesc.getPriAmmoItemType(), event.getPrimaryAmmo());
1171 }
1172 if (weaponDesc.getSecAmmoItemType() != null && weaponDesc.getSecAmmoItemType() != weaponDesc.getPriAmmoItemType()) {
1173 ammo.weaponUpdate(weaponDesc.getSecAmmoItemType(), event.getSecondaryAmmo());
1174 }
1175
1176 Weapon weapon = weaponsByItemType.all.get(weaponDesc.getPickupType());
1177 if (weapon != null) {
1178 ammo.updateWeaponAmmo(weapon);
1179 }
1180 }
1181
1182
1183
1184
1185
1186 public WeaponUpdateListener(IWorldView worldView) {
1187 worldView.addEventListener(WeaponUpdate.class, this);
1188 }
1189 }
1190
1191 WeaponUpdateListener weaponUpdateListener;
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201 private class SelfUpdateListener implements IWorldObjectEventListener<Self, WorldObjectUpdatedEvent<Self>> {
1202
1203 public void notify(WorldObjectUpdatedEvent<Self> event) {
1204 if (event == null) return;
1205
1206
1207 if (self == null) {
1208 self = event.getObject();
1209 }
1210
1211 Weapon weaponToUpdate = getCurrentWeapon();
1212 if (weaponToUpdate != null) {
1213 WeaponDescriptor weaponDesc = weaponToUpdate.getDescriptor();
1214 if (weaponDesc == null) {
1215 if (log.isLoggable(Level.WARNING)) log.warning("SelfUpdateListener.notify(): There is no weapon descriptor for the weapon " + weaponToUpdate);
1216 return;
1217 }
1218 if (weaponDesc.getPriAmmoItemType() != null) {
1219 ammo.weaponUpdate(weaponDesc.getPriAmmoItemType(), self.getPrimaryAmmo());
1220 }
1221 if (weaponDesc.getSecAmmoItemType() != null && weaponDesc.getSecAmmoItemType() != weaponDesc.getPriAmmoItemType()) {
1222 ammo.weaponUpdate(weaponDesc.getSecAmmoItemType(), self.getSecondaryAmmo());
1223 }
1224 ammo.updateWeaponAmmo(weaponToUpdate);
1225 }
1226 }
1227
1228
1229
1230
1231
1232 public SelfUpdateListener(IWorldView worldView) {
1233 worldView.addObjectListener(Self.class, WorldObjectUpdatedEvent.class, this);
1234 }
1235 }
1236
1237
1238 SelfUpdateListener selfUpdateListener;
1239
1240
1241
1242
1243
1244
1245
1246 private class ThrownListener implements IWorldEventListener<Thrown> {
1247
1248 @Override
1249 public void notify(Thrown event) {
1250 WeaponDescriptor desc = inventoryUnrealIdToWeaponDescriptor.get(event.getId());
1251 if (desc == null) {
1252 if (log.isLoggable(Level.WARNING)) log.warning("ThrownListener.notify(): There is no known weapon descriptor for id " + event.getId() + " inside Weaponary.");
1253 return;
1254 }
1255 ItemType weaponType = desc.getPickupType();
1256 weaponsByGroup.remove(weaponType.getGroup());
1257 weaponsByItemType.remove(weaponType);
1258 }
1259
1260
1261
1262
1263
1264 public ThrownListener(IWorldView worldView) {
1265 worldView.addEventListener(Thrown.class, this);
1266 }
1267 }
1268
1269 ThrownListener thrownListener;
1270
1271
1272
1273
1274
1275
1276
1277 private class BotKilledListener implements IWorldEventListener<BotKilled> {
1278
1279 @Override
1280 public void notify(BotKilled event) {
1281 ammo.botKilled();
1282 weaponsByGroup.botKilled();
1283 weaponsByItemType.botKilled();
1284 weaponsById.botKilled();
1285 weaponTypeToInventoryUnrealId.clear();
1286 inventoryUnrealIdToWeaponDescriptor.clear();
1287 }
1288
1289
1290
1291
1292
1293 public BotKilledListener(IWorldView worldView) {
1294 worldView.addEventListener(BotKilled.class, this);
1295 }
1296
1297 }
1298
1299 BotKilledListener botKilledListener;
1300
1301
1302
1303 ItemDescriptors itemDescriptors;
1304
1305
1306
1307 private Self self = null;
1308
1309
1310
1311
1312
1313 public Weaponry(UT2004Bot bot) {
1314 this(bot, new ItemDescriptors(bot));
1315 }
1316
1317
1318
1319
1320
1321
1322
1323 public Weaponry(UT2004Bot bot, ItemDescriptors itemDescriptors) {
1324 this(bot, itemDescriptors, null);
1325 }
1326
1327
1328
1329
1330
1331
1332
1333
1334 public Weaponry(UT2004Bot bot, ItemDescriptors descriptors, LogCategory moduleLog) {
1335 super(bot);
1336
1337 this.itemDescriptors = descriptors;
1338
1339 if (this.itemDescriptors == null) {
1340 this.itemDescriptors = new ItemDescriptors(bot, moduleLog);
1341 }
1342
1343
1344 addInventoryMsgListener = new AddInventoryMsgListener(worldView);
1345 itemPickedUpListener = new ItemPickedUpListener(worldView);
1346 weaponUpdateListener = new WeaponUpdateListener(worldView);
1347 selfUpdateListener = new SelfUpdateListener(worldView);
1348 thrownListener = new ThrownListener(worldView);
1349 botKilledListener = new BotKilledListener(worldView);
1350
1351 cleanUp();
1352 }
1353
1354 @Override
1355 protected void cleanUp() {
1356 super.cleanUp();
1357
1358 ammo.botKilled();
1359 weaponsByGroup.botKilled();
1360 weaponsByItemType.botKilled();
1361 weaponsById.botKilled();
1362 weaponTypeToInventoryUnrealId.clear();
1363 inventoryUnrealIdToWeaponDescriptor.clear();
1364 }
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374 public int getMaxAmmo(ItemType ammoType) {
1375 if (ammoType == null) return 0;
1376 WeaponDescriptor weapon = getWeaponDescriptor( getWeaponForAmmo(ammoType) );
1377 if (weapon == null) {
1378 if (log.isLoggable(Level.WARNING)) log.warning("There is no known weapon descriptor for item type " + ammoType + " inside Weaponary.");
1379 return 0;
1380 }
1381 if ( weapon.getPriAmmoItemType() == ammoType ) {
1382 return weapon.getPriMaxAmount();
1383 } else if ( weapon.getSecAmmoItemType() == ammoType ) {
1384 return weapon.getSecMaxAmount();
1385 } else {
1386 return 0;
1387 }
1388 }
1389
1390 }