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