1 package nl.tudelft.pogamut.ut2004.agent.module.shooting.weapon;
2
3 import nl.tudelft.pogamut.ut2004.agent.module.sensor.Projectiles;
4 import nl.tudelft.pogamut.ut2004.agent.module.shooting.AbstractWeaponShooting;
5 import nl.tudelft.pogamut.ut2004.agent.module.shooting.util.FacingUtil;
6 import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
7 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
8 import cz.cuni.amis.pogamut.ut2004.agent.module.sensomotoric.Weaponry;
9 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.AgentInfo;
10 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.WeaponPref;
11 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.WeaponPrefs;
12 import cz.cuni.amis.pogamut.ut2004.bot.command.AdvancedShooting;
13 import cz.cuni.amis.pogamut.ut2004.bot.command.ImprovedShooting;
14 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
15 import cz.cuni.amis.pogamut.ut2004.communication.messages.ItemType;
16 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.IncomingProjectile;
17 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Player;
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class ShockRifleShooting extends AbstractWeaponShooting {
50
51
52
53
54 protected static final int SHIELD_GUN_DEFLECT_ANGLE = 90;
55
56
57
58
59 protected static final WeaponPref SHOCK_RIFLE_PRIMARY = new WeaponPref(ItemType.SHOCK_RIFLE, true);
60
61
62
63
64 protected static final WeaponPref SHOCK_RIFLE_SECONDARY = new WeaponPref(ItemType.SHOCK_RIFLE, false);
65
66
67
68
69
70 protected static final double SHOCK_RIFLE_COMBO_RADIUS = 300;
71
72
73
74
75 protected static final double SHOCK_RIFLE_PROJECTILE_SPLASH_RADIUS = 150;
76
77
78
79
80 protected static final int SHOCK_RIFLE_PROJECTILE_DAMAGE = 35;
81
82
83
84
85
86 protected static final int SHOCK_RIFLE_MIN_DISTANCE_COMBO = 900;
87
88 protected Projectiles projectiles;
89
90
91
92
93
94 protected Location lastLocation;
95
96 public ShockRifleShooting(UT2004Bot<?, ?, ?> bot, AgentInfo info, ImprovedShooting shoot, Weaponry weaponry,
97 Projectiles projectiles) {
98 super(bot, info, shoot, weaponry);
99
100 this.weaponry = weaponry;
101 this.projectiles = projectiles;
102
103 }
104
105
106
107
108 @Override
109 protected void shoot() {
110
111
112 if (!isWeaponReady()) {
113 return;
114 }
115
116
117 if (!hasTarget()) {
118 return;
119 }
120
121
122 this.focus.setFocus(target);
123
124 boolean safeToSHoot = isSafeToShoot(target, weaponPref);
125 boolean facing = FacingUtil.isFacing2D(info, target, FACING_ANGLE);
126
127
128 if (!(target instanceof Player)) {
129 shootTarget(safeToSHoot, facing);
130 return;
131 }
132
133 Player player = (Player) target;
134
135
136
137 if (shootCombo(player)) {
138 return;
139 }
140
141
142 if (!player.isVisible()) {
143 shoot.stopShooting();
144 return;
145 }
146
147
148
149 lastLocation = player.getLocation();
150
151 boolean targetFacing = FacingUtil.isFacing2D(player, agent, SHIELD_GUN_DEFLECT_ANGLE);
152 boolean targetShieldGun = ItemType.SHIELD_GUN.equals(ItemType.getItemType(player.getWeapon()));
153 boolean targetShielded = player.getFiring() == 2;
154 boolean targetCanDeflect = targetShieldGun && targetFacing && targetShielded;
155
156
157
158
159
160 shootPlayer(safeToSHoot, targetCanDeflect, facing);
161
162 }
163
164
165
166
167
168
169
170
171
172 protected void shootPlayer(boolean safeToSHoot, boolean canDeflect, boolean facing) {
173 if (!canDeflect) {
174 shootTarget(safeToSHoot, facing);
175 } else {
176 shootShieldedPlayer(safeToSHoot, facing);
177 }
178 }
179
180 protected void shootShieldedPlayer(boolean safeToSHoot, boolean facing) {
181 boolean inComboRange = target.getLocation().getDistance(agent.getLocation()) >= SHOCK_RIFLE_MIN_DISTANCE_COMBO
182 - SHOCK_RIFLE_COMBO_RADIUS;
183
184 log.fine(String.format("Shooting shielded player. safeToSHoot=%s facing=%s inComboRange=%s", safeToSHoot,
185 facing, inComboRange));
186 if (inComboRange && safeToSHoot && facing && weaponPref.isSecondary()) {
187 shoot.shoot(weaponPref, target.getLocation().add(ABOVE_PLAYER_OFFSET));
188 } else {
189 shoot.stopShooting();
190 }
191
192 }
193
194
195
196
197
198
199
200
201 protected void shootTarget(boolean safeToSHoot, boolean facing) {
202 log.fine(String.format("Shooting target. safeToSHoot=%s facing=%s ", safeToSHoot, facing));
203 if (safeToSHoot && facing) {
204 shoot.shoot(weaponPref, target);
205 } else if (facing) {
206 shoot.shoot(SHOCK_RIFLE_PRIMARY, target);
207 } else {
208 shoot.stopShooting();
209 }
210 }
211
212
213
214
215
216
217
218
219
220 protected boolean isSafeToShoot(ILocated target, WeaponPref weaponPref) {
221 boolean primary = weaponPref.isPrimary();
222
223 double distance = info.getLocation().getDistance(target.getLocation());
224 boolean safeDistance = distance > SHOCK_RIFLE_PROJECTILE_SPLASH_RADIUS;
225 boolean healty = info.getHealth() > SHOCK_RIFLE_PROJECTILE_DAMAGE;
226
227 return (primary || safeDistance || healty);
228 }
229
230
231
232
233
234
235
236
237 protected boolean shootCombo(Player target) {
238
239 IncomingProjectile projectile;
240
241
242
243 if (target.isVisible()) {
244 projectile = projectiles.getNearestProjectile(target, ItemType.SHOCK_RIFLE_PROJECTILE);
245 } else {
246 projectile = projectiles.getNearestProjectile(lastLocation, ItemType.SHOCK_RIFLE_PROJECTILE);
247 }
248
249 if (projectile != null) {
250
251 if (projectile.getImpactTime() < 0) {
252 System.out.println("BUG!");
253 }
254
255 double distanceOrbTarget = projectile.getLocation().getDistance(target.getLocation());
256 double distanceSelfTarget = info.getLocation().getDistance(target.getLocation());
257 double distanceSelfOrb = info.getLocation().getDistance(projectile.getLocation());
258
259 boolean orbPassedTarget = distanceSelfOrb > distanceSelfTarget + SHOCK_RIFLE_COMBO_RADIUS;
260 boolean targetInComboRadius = distanceOrbTarget < SHOCK_RIFLE_COMBO_RADIUS;
261
262 log.fine(String.format("Selected projectile: %s", projectile));
263 log.fine(String.format("Projectile has passed target? %s", orbPassedTarget));
264 log.fine(String.format("Target in combo radius? %s", targetInComboRadius));
265
266
267
268
269
270 if (!orbPassedTarget && !targetInComboRadius) {
271 log.fine("Waiting for projectile to close in on target");
272 shoot.stopShooting();
273 focus.setFocus((ILocated) projectile);
274 return true;
275 }
276
277 else if (!orbPassedTarget) {
278 log.fine("Shoot rojectile");
279
280 shoot.shoot(SHOCK_RIFLE_PRIMARY, projectile.getId());
281
282 return true;
283 }
284 }
285 log.fine("No valid projectile to shoot");
286 return false;
287 }
288
289 @Override
290 protected WeaponPref getDefaultWeaponPref() {
291 return SHOCK_RIFLE_SECONDARY;
292 }
293
294 }