1 package nl.tudelft.pogamut.ut2004.agent.module.shooting.weapon;
2
3 import nl.tudelft.pogamut.unreal.agent.module.sensor.Projectiles;
4 import nl.tudelft.pogamut.unreal.agent.module.shooting.AbstractWeaponShooting;
5 import nl.tudelft.pogamut.unreal.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.UT2004ItemType;
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(UT2004ItemType.SHOCK_RIFLE, true);
60
61
62
63
64 protected static final WeaponPref SHOCK_RIFLE_SECONDARY = new WeaponPref(UT2004ItemType.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
117 if (!hasTarget() && shootCombo(lastLocation)) {
118 return;
119 }
120
121
122
123 lastLocation = null;
124
125
126 if (!hasTarget()) {
127 shoot.stopShooting();
128 return;
129 }
130
131
132 this.focus.setFocus(target);
133
134 boolean safeToSHoot = isSafeToShoot(target, weaponPref);
135 boolean facing = FacingUtil.isFacing2D(info, target, FACING_ANGLE);
136
137
138 if (!(target instanceof Player)) {
139 shootTarget(safeToSHoot, facing);
140 return;
141 }
142
143 Player player = (Player) target;
144
145
146
147 if (shootCombo(player)) {
148 return;
149 }
150
151
152 if (!player.isVisible()) {
153 shoot.stopShooting();
154 return;
155 }
156
157
158
159 lastLocation = player.getLocation();
160
161 boolean targetFacing = FacingUtil.isFacing2D(player, agent, SHIELD_GUN_DEFLECT_ANGLE);
162 boolean targetShieldGun = UT2004ItemType.SHIELD_GUN.equals(UT2004ItemType.getItemType(player.getWeapon()));
163 boolean targetShielded = player.getFiring() == 2;
164 boolean targetCanDeflect = targetShieldGun && targetFacing && targetShielded;
165
166
167
168
169
170 shootPlayer(safeToSHoot, targetCanDeflect, facing);
171
172 }
173
174
175
176
177
178
179
180
181
182 protected void shootPlayer(boolean safeToSHoot, boolean canDeflect, boolean facing) {
183 if (!canDeflect) {
184 shootTarget(safeToSHoot, facing);
185 } else {
186 shootShieldedPlayer(safeToSHoot, facing);
187 }
188 }
189
190 protected void shootShieldedPlayer(boolean safeToSHoot, boolean facing) {
191 boolean inComboRange = target.getLocation().getDistance(agent.getLocation()) >= SHOCK_RIFLE_MIN_DISTANCE_COMBO
192 - SHOCK_RIFLE_COMBO_RADIUS;
193
194 log.fine(String.format("Shooting shielded player. safeToSHoot=%s facing=%s inComboRange=%s", safeToSHoot, facing, inComboRange));
195 if (inComboRange && safeToSHoot && facing && weaponPref.isSecondary()) {
196 shoot.shoot(weaponPref, target.getLocation().add(ABOVE_PLAYER_OFFSET));
197 } else {
198 shoot.stopShooting();
199 }
200
201 }
202
203
204
205
206
207
208
209
210 protected void shootTarget(boolean safeToSHoot, boolean facing) {
211 log.fine(String.format("Shooting target. safeToSHoot=%s facing=%s ", safeToSHoot, facing));
212 if (safeToSHoot && facing) {
213 shoot.shoot(weaponPref, target);
214 } else if (facing) {
215 shoot.shoot(SHOCK_RIFLE_PRIMARY, target);
216 } else {
217 shoot.stopShooting();
218 }
219 }
220
221
222
223
224
225
226
227
228
229 protected boolean isSafeToShoot(ILocated target, WeaponPref weaponPref) {
230 boolean primary = weaponPref.isPrimary();
231
232 double distance = info.getLocation().getDistance(target.getLocation());
233 boolean safeDistance = distance > SHOCK_RIFLE_PROJECTILE_SPLASH_RADIUS;
234 boolean healty = info.getHealth() > SHOCK_RIFLE_PROJECTILE_DAMAGE;
235
236 return (primary || safeDistance || healty);
237 }
238
239 protected boolean shootCombo(ILocated target) {
240 if (target == null || target.getLocation() == null) {
241 log.fine("No valid target");
242 return false;
243 }
244
245 IncomingProjectile projectile = projectiles.getNearestProjectile(target, UT2004ItemType.SHOCK_RIFLE_PROJECTILE);
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 }