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, Projectiles projectiles) {
97 super(bot, info, shoot, weaponry);
98
99 this.weaponry = weaponry;
100 this.projectiles = projectiles;
101
102 }
103
104
105
106
107 @Override
108 protected void shoot() {
109
110
111 if (!isWeaponReady()) {
112 return;
113 }
114
115
116 if (!hasTarget()) {
117 return;
118 }
119
120
121 this.focus.setFocus(target);
122
123 boolean safeToSHoot = isSafeToShoot(target, weaponPref);
124 boolean facing = FacingUtil.isFacing2D(info, target, FACING_ANGLE);
125
126
127 if (!(target instanceof Player)) {
128 shootTarget(safeToSHoot, facing);
129 return;
130 }
131
132 Player player = (Player) target;
133
134
135
136 if (shootCombo(player)) {
137 return;
138 }
139
140
141 if (!player.isVisible()) {
142 shoot.stopShooting();
143 return;
144 }
145
146
147
148 lastLocation = player.getLocation();
149
150 boolean targetFacing = FacingUtil.isFacing2D(player, agent, SHIELD_GUN_DEFLECT_ANGLE);
151 boolean targetShieldGun = ItemType.SHIELD_GUN.equals(ItemType.getItemType(player.getWeapon()));
152 boolean targetShielded = player.getFiring() == 2;
153 boolean targetCanDeflect = targetShieldGun && targetFacing && targetShielded;
154
155
156
157
158
159 shootPlayer(safeToSHoot, targetCanDeflect, facing);
160
161 }
162
163
164
165
166
167
168
169
170
171 protected void shootPlayer(boolean safeToSHoot, boolean canDeflect, boolean facing) {
172 if (!canDeflect) {
173 shootTarget(safeToSHoot, facing);
174 } else {
175 shootShieldedPlayer(safeToSHoot, facing);
176 }
177 }
178
179 protected void shootShieldedPlayer(boolean safeToSHoot, boolean facing) {
180 boolean inComboRange = target.getLocation().getDistance(agent.getLocation()) >= SHOCK_RIFLE_MIN_DISTANCE_COMBO
181 - SHOCK_RIFLE_COMBO_RADIUS;
182
183 log.fine(String.format("Shooting shielded player. safeToSHoot=%s facing=%s inComboRange=%s", safeToSHoot, facing, inComboRange));
184 if (inComboRange && safeToSHoot && facing && weaponPref.isSecondary()) {
185 shoot.shoot(weaponPref, target.getLocation().add(ABOVE_PLAYER_OFFSET));
186 } else {
187 shoot.stopShooting();
188 }
189
190 }
191
192
193
194
195
196
197
198
199 protected void shootTarget(boolean safeToSHoot, boolean facing) {
200 log.fine(String.format("Shooting target. safeToSHoot=%s facing=%s ", safeToSHoot, facing));
201 if (safeToSHoot && facing) {
202 shoot.shoot(weaponPref, target);
203 } else if (facing) {
204 shoot.shoot(SHOCK_RIFLE_PRIMARY, target);
205 } else {
206 shoot.stopShooting();
207 }
208 }
209
210
211
212
213
214
215
216
217
218 protected boolean isSafeToShoot(ILocated target, WeaponPref weaponPref) {
219 boolean primary = weaponPref.isPrimary();
220
221 double distance = info.getLocation().getDistance(target.getLocation());
222 boolean safeDistance = distance > SHOCK_RIFLE_PROJECTILE_SPLASH_RADIUS;
223 boolean healty = info.getHealth() > SHOCK_RIFLE_PROJECTILE_DAMAGE;
224
225 return (primary || safeDistance || healty);
226 }
227
228
229
230
231
232
233
234
235 protected boolean shootCombo(Player target) {
236
237 IncomingProjectile projectile;
238
239
240
241 if (target.isVisible()) {
242 projectile = projectiles.getNearestProjectile(target, ItemType.SHOCK_RIFLE_PROJECTILE);
243 } else {
244 projectile = projectiles.getNearestProjectile(lastLocation, ItemType.SHOCK_RIFLE_PROJECTILE);
245 }
246
247 if (projectile == null) {
248 log.fine("No valid projectile to shoot");
249 return false;
250 }
251
252 double distanceOrbTarget = projectile.getLocation().getDistance(target.getLocation());
253 double distanceSelfTarget = info.getLocation().getDistance(target.getLocation());
254 double distanceSelfOrb = info.getLocation().getDistance(projectile.getLocation());
255
256 boolean orbPassedTarget = distanceSelfOrb > distanceSelfTarget + SHOCK_RIFLE_COMBO_RADIUS;
257 boolean targetInComboRadius = distanceOrbTarget < SHOCK_RIFLE_COMBO_RADIUS;
258
259 log.fine(String.format("Selected projectile: %s", projectile));
260 log.fine(String.format("Projectile has passed target? %s", orbPassedTarget));
261 log.fine(String.format("Target in combo radius? %s", targetInComboRadius));
262
263
264
265
266
267 if (!orbPassedTarget && !targetInComboRadius) {
268 log.fine("Waiting for projectile to close in on target");
269 shoot.stopShooting();
270 focus.setFocus((ILocated) projectile);
271 return true;
272 }
273
274 else if (!orbPassedTarget) {
275 log.fine("Shoot rojectile");
276 shoot.shoot(SHOCK_RIFLE_PRIMARY, projectile.getId());
277 return true;
278 }
279
280 return false;
281 }
282
283 @Override
284 protected WeaponPref getDefaultWeaponPref() {
285 return SHOCK_RIFLE_SECONDARY;
286 }
287
288 }