1 .vector personal_v_angle; // view angles to restore on impulse 77
2 .vector personal_velocity; // velocity to restore on impulse 77
4 void CopyBody(float keepvelocity);
6 // changes by LordHavoc on 03/30/04
7 // cleaned up dummy code
8 // dummies are now removed eventually after being gibbed (norespawn = TRUE)
9 // dummy impulse now checks sv_cheats to prevent players from overwhelming server with dummies
10 // dummies now use player code where possible
12 void player_anim (void);
15 self.think = DummyThink;
16 self.nextthink = time;
24 void printsurfaceinfo(entity e, vector v)
26 local float surfnum, numpoints, vnum;
29 surfnum = getsurfacenearpoint(e, v);
32 sprint(self, "texture: ");
33 s = getsurfacetexture(e, surfnum);
35 sprint(self, " normal: ");
36 n = getsurfacenormal(e, surfnum);
37 sprint(self, vtos(n));
39 numpoints = getsurfacenumpoints(e, surfnum);
40 sprint(self, ftos(numpoints));
41 sprint(self, " verts:");
43 while (vnum < numpoints)
46 n = getsurfacepoint(e, surfnum, vnum);
47 sprint(self, vtos(n));
50 sprint(self, " point tested: ");
51 sprint(self, vtos(v));
52 sprint(self, " nearest point on surface: ");
53 n = getsurfaceclippedpoint(e, surfnum, v);
54 sprint(self, vtos(n));
62 * 0 reserved (no input)
63 * 1 to 9: weapon shortcuts
65 * 11: most recently used weapon
70 * 30 to 39: create waypoints
71 * 47: clear personal waypoints
72 * 48: clear team waypoints
73 * 49: turn base waypoints on/off
80 * 143: emergency teleport
81 * 144: printsurfaceinfo
85 * 200 to 209: prev weapon shortcuts
86 * 210 to 219: best weapon shortcuts
87 * 220 to 229: next weapon shortcuts
88 * 230 to 253: individual weapons (up to 24)
91 void ImpulseCommands (void)
94 vector start, end, enddown;
97 float good, evil, evilsurf;
104 if (!imp || gameover)
108 if (timeoutStatus == 2) //don't allow any impulses while the game is paused
111 if (imp >= 1 && imp <= 9)
113 // weapon switching impulses
114 if(self.deadflag == DEAD_NO)
115 W_NextWeaponOnImpulse(imp);
117 self.impulse = imp; // retry in next frame
119 else if(imp >= 10 && imp <= 17)
121 if(self.deadflag == DEAD_NO)
129 W_SwitchWeapon (self.cnt); // previously used
135 W_SwitchWeapon (w_getbestweapon(self));
138 W_NextWeaponOnImpulse(0);
142 W_ThrowWeapon(W_CalculateProjectileVelocity(self.velocity, v_forward * 750), '0 0 0', TRUE);
147 self.impulse = imp; // retry in next frame
149 else if(imp >= 200 && imp <= 229)
151 if(self.deadflag == DEAD_NO)
153 // custom order weapon cycling
155 m = (imp - (210 + i)); // <0 for prev, =0 for best, >0 for next
156 W_CycleWeapon(self.(cvar_cl_weaponpriorities[i]), m);
159 self.impulse = imp; // retry in next frame
161 else if(imp >= 230 && imp <= 253)
163 if(self.deadflag == DEAD_NO)
164 W_SwitchWeapon (imp - 230 + WEP_FIRST);
166 self.impulse = imp; // retry in next frame
169 else if (imp >= 30 && imp <= 49)
174 WaypointSprite_DeployPersonal("waypoint", self.origin);
175 self.personal_v_angle = self.v_angle;
176 self.personal_velocity = self.velocity;
177 sprint(self, "personal waypoint spawned at location\n");
180 WaypointSprite_DeployPersonal("waypoint", self.cursor_trace_endpos);
181 self.personal_v_angle = self.v_angle;
182 self.personal_velocity = '0 0 0';
183 sprint(self, "personal waypoint spawned at crosshair\n");
186 if(vlen(self.death_origin))
188 WaypointSprite_DeployPersonal("waypoint", self.death_origin);
189 self.personal_v_angle = self.v_angle;
190 self.personal_velocity = '0 0 0';
191 sprint(self, "personal waypoint spawned at death location\n");
195 if(self.deadflag == DEAD_NO && teams_matter)
197 WaypointSprite_Attach("helpme", TRUE);
198 sprint(self, "HELP ME attached\n");
202 WaypointSprite_DeployFixed("here", FALSE, self.origin);
203 sprint(self, "HERE spawned at location\n");
206 WaypointSprite_DeployFixed("here", FALSE, self.cursor_trace_endpos);
207 sprint(self, "HERE spawned at crosshair\n");
210 if(vlen(self.death_origin))
212 WaypointSprite_DeployFixed("here", FALSE, self.death_origin);
213 sprint(self, "HERE spawned at death location\n");
217 WaypointSprite_DeployFixed("danger", FALSE, self.origin);
218 sprint(self, "DANGER spawned at location\n");
221 WaypointSprite_DeployFixed("danger", FALSE, self.cursor_trace_endpos);
222 sprint(self, "DANGER spawned at crosshair\n");
225 if(vlen(self.death_origin))
227 WaypointSprite_DeployFixed("danger", FALSE, self.death_origin);
228 sprint(self, "DANGER spawned at death location\n");
232 WaypointSprite_ClearPersonal();
233 sprint(self, "personal waypoint cleared\n");
236 WaypointSprite_ClearOwned();
237 sprint(self, "all waypoints cleared\n");
240 self.cvar_cl_hidewaypoints = !(self.cvar_cl_hidewaypoints);
241 sprint(self, "fixed waypoints now ");
242 if(self.cvar_cl_hidewaypoints)
243 sprint(self, "OFF\n");
245 sprint(self, "ON\n");
249 else if(imp >= 140 && imp <= 149 || imp == 99) // 10 cheats ought to be enough for anyone
252 if(self.deadflag == DEAD_NO)
257 self.weapons |= WEPBIT_ALL;
258 self.ammo_shells = g_pickup_shells_max;
259 self.ammo_nails = g_pickup_nails_max;
260 self.ammo_rockets = g_pickup_rockets_max;
261 self.ammo_cells = g_pickup_cells_max;
262 self.health = g_pickup_healthsmall_max;
263 self.armorvalue = g_pickup_armorsmall_max;
264 self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
265 self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
266 self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
267 // precache weapon models/sounds
269 while (wep <= WEP_LAST)
271 weapon_action(wep, WR_PRECACHE);
276 makevectors (self.v_angle);
277 self.velocity = self.velocity + v_forward * 300;
280 self.velocity = self.velocity - v_forward * 300;
283 if(self.waypointsprite_deployed_personal)
285 self.speedrunning = TRUE;
286 tracebox(self.waypointsprite_deployed_personal.origin, self.mins, self.maxs, self.waypointsprite_deployed_personal.origin, MOVE_WORLDONLY, self);
289 sprint(self, "Cannot move there, cheater - only waypoints set using g_waypointsprite_personal work\n");
293 // Abort speedrun, teleport back
294 setorigin(self, self.waypointsprite_deployed_personal.origin);
295 self.oldvelocity = self.velocity = self.personal_velocity;
296 self.angles = self.personal_v_angle;
297 self.fixangle = TRUE;
300 bprint("The ", self.flagcarried.netname, " was returned to base by its carrier\n");
301 ReturnFlag(self.flagcarried);
304 self.ammo_rockets = 999;
305 self.ammo_nails = 999;
306 self.ammo_cells = 999;
307 self.ammo_shells = 999;
308 self.health = start_health;
309 self.armorvalue = start_armorvalue;
310 self.weapons |= weaponsInMap;
311 self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
312 self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
313 self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
315 else if(self.deadflag != DEAD_NO)
316 sprint(self, "UR DEAD AHAHAH))\n");
318 sprint(self, "No waypoint set, cheater (use g_waypointsprite_personal to set one)\n");
325 good = DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP;
326 evil = DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER;
327 evilsurf = Q3SURFACEFLAG_SKY;
329 m = self.dphitcontentsmask;
330 self.dphitcontentsmask = good | evil;
333 delta = world.maxs - world.mins;
335 maxattempts = ((sv_cheats >= 2) ? 100000 : 100);
337 for(i = 0; i < maxattempts; ++i)
339 start_x = org_x + random() * delta_x;
340 start_y = org_y + random() * delta_y;
341 start_z = org_z + random() * delta_z;
343 // rule 1: start inside world bounds, and outside
344 // solid, and don't start from somewhere where you can
346 tracebox(start, self.mins, self.maxs, start - '0 0 1' * delta_z, MOVE_NORMAL, self);
347 if(trace_fraction >= 1)
351 dprint("hit contents ", ftos(trace_dphitcontents), "\n");
352 if(trace_dphitcontents & evil)
354 if(trace_dphitq3surfaceflags & evilsurf)
357 // rule 2: if we are too high, lower the point
358 if(trace_fraction * delta_z > 1024)
359 start = trace_endpos + '0 0 1024';
360 enddown = trace_endpos;
362 // these can be traceLINES as we already verified the starting box
363 traceline(start, start + '1 0 0' * delta_x, MOVE_NORMAL, self);
364 if(trace_fraction >= 1)
366 traceline(start, start - '1 0 0' * delta_x, MOVE_NORMAL, self);
367 if(trace_fraction >= 1)
369 traceline(start, start + '0 1 0' * delta_y, MOVE_NORMAL, self);
370 if(trace_fraction >= 1)
372 traceline(start, start - '0 1 0' * delta_y, MOVE_NORMAL, self);
373 if(trace_fraction >= 1)
375 traceline(start, start + '0 0 1' * delta_z, MOVE_NORMAL, self);
376 if(trace_fraction >= 1)
379 end_x = org_x + random() * delta_x;
380 end_y = org_y + random() * delta_y;
381 end_z = org_z + random() * delta_z;
382 end = start + normalize(end - start) * vlen(delta);
384 // rule 3: start TO end must not be too short
385 tracebox(start, self.mins, self.maxs, end, MOVE_NORMAL, self);
388 if(trace_fraction < 256 / vlen(delta))
391 // rule 4: don't want to look at sky
392 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
395 // rule 5: we must not end up in trigger_hurt
396 if(tracebox_hits_trigger_hurt(start, self.mins, self.maxs, enddown))
398 dprint("trigger_hurt! ouch! and nothing else could find it!\n");
408 self.angles = vectoangles(end - start);
409 self.angles_x = -self.angles_x;
410 self.fixangle = TRUE;
411 self.velocity = '0 0 0';
412 dprint("Needed ", ftos(i + 1), " attempts\n");
415 sprint(self, "Emergency teleport could not find a good location, forget it!\n");
417 self.dphitcontentsmask = m;
420 makevectors(self.v_angle);
421 traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * MAX_SHOT_DISTANCE, FALSE, self);
422 if (trace_fraction < 1)
423 printsurfaceinfo(trace_ent, trace_endpos);
426 makevectors(self.v_angle);
427 traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 65536, FALSE, self);
428 sprint(self, strcat("distance: ", ftos(fabs(vlen(trace_endpos - (self.origin + self.view_ofs)))), "\n"));
433 else if(imp >= 103 && imp <= 106)
435 if(cvar("g_waypointeditor"))
440 waypoint_schedulerelink(waypoint_spawn(self.origin, self.origin, 0));
443 e = navigation_findnearestwaypoint(self, FALSE);
448 waypoint_schedulerelinkall();
457 //TetrisImpulses(imp);