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)
118 case 1: W_CycleWeapon("1", 0); break;
119 case 2: W_CycleWeapon("2", 0); break;
120 case 3: W_CycleWeapon("3", 0); break;
121 case 4: W_CycleWeapon("4", 0); break;
122 case 5: W_CycleWeapon("5", 0); break;
123 case 6: W_CycleWeapon("6", 0); break;
124 case 7: W_CycleWeapon("7", 0); break;
125 case 8: W_CycleWeapon("8", 0); break;
126 case 9: W_CycleWeapon("9", 0); break;
130 self.impulse = imp; // retry in next frame
132 else if(imp >= 10 && imp <= 17)
134 if(self.deadflag == DEAD_NO)
142 W_SwitchWeapon (self.cnt); // previously used
148 W_SwitchWeapon (w_getbestweapon(self));
152 W_ThrowWeapon(W_CalculateProjectileVelocity(self.velocity, v_forward * 750), '0 0 0', TRUE);
157 self.impulse = imp; // retry in next frame
159 else if(imp >= 200 && imp <= 229)
161 if(self.deadflag == DEAD_NO)
163 // custom order weapon cycling
165 m = (imp - (210 + i)); // <0 for prev, =0 for best, >0 for next
166 W_CycleWeapon(self.(cvar_cl_weaponpriorities[i]), m);
169 self.impulse = imp; // retry in next frame
171 else if(imp >= 230 && imp <= 253)
173 if(self.deadflag == DEAD_NO)
174 W_SwitchWeapon (imp - 230 + WEP_FIRST);
176 self.impulse = imp; // retry in next frame
179 else if (imp >= 30 && imp <= 49)
184 WaypointSprite_DeployPersonal("waypoint", self.origin);
185 self.personal_v_angle = self.v_angle;
186 self.personal_velocity = self.velocity;
187 sprint(self, "personal waypoint spawned at location\n");
190 WaypointSprite_DeployPersonal("waypoint", self.cursor_trace_endpos);
191 self.personal_v_angle = self.v_angle;
192 self.personal_velocity = '0 0 0';
193 sprint(self, "personal waypoint spawned at crosshair\n");
196 if(vlen(self.death_origin))
198 WaypointSprite_DeployPersonal("waypoint", self.death_origin);
199 self.personal_v_angle = self.v_angle;
200 self.personal_velocity = '0 0 0';
201 sprint(self, "personal waypoint spawned at death location\n");
205 if(self.deadflag == DEAD_NO && teams_matter)
207 WaypointSprite_Attach("helpme", TRUE);
208 sprint(self, "HELP ME attached\n");
212 WaypointSprite_DeployFixed("here", FALSE, self.origin);
213 sprint(self, "HERE spawned at location\n");
216 WaypointSprite_DeployFixed("here", FALSE, self.cursor_trace_endpos);
217 sprint(self, "HERE spawned at crosshair\n");
220 if(vlen(self.death_origin))
222 WaypointSprite_DeployFixed("here", FALSE, self.death_origin);
223 sprint(self, "HERE spawned at death location\n");
227 WaypointSprite_DeployFixed("danger", FALSE, self.origin);
228 sprint(self, "DANGER spawned at location\n");
231 WaypointSprite_DeployFixed("danger", FALSE, self.cursor_trace_endpos);
232 sprint(self, "DANGER spawned at crosshair\n");
235 if(vlen(self.death_origin))
237 WaypointSprite_DeployFixed("danger", FALSE, self.death_origin);
238 sprint(self, "DANGER spawned at death location\n");
242 WaypointSprite_ClearPersonal();
243 sprint(self, "personal waypoint cleared\n");
246 WaypointSprite_ClearOwned();
247 sprint(self, "all waypoints cleared\n");
250 self.cvar_cl_hidewaypoints = !(self.cvar_cl_hidewaypoints);
251 sprint(self, "fixed waypoints now ");
252 if(self.cvar_cl_hidewaypoints)
253 sprint(self, "OFF\n");
255 sprint(self, "ON\n");
259 else if(imp >= 140 && imp <= 149 || imp == 99) // 10 cheats ought to be enough for anyone
262 if(self.deadflag == DEAD_NO)
267 self.items |= (IT_LASER | IT_UZI | IT_SHOTGUN | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER);
268 self.ammo_shells = g_pickup_shells_max;
269 self.ammo_nails = g_pickup_nails_max;
270 self.ammo_rockets = g_pickup_rockets_max;
271 self.ammo_cells = g_pickup_cells_max;
272 self.health = g_pickup_healthsmall_max;
273 self.armorvalue = g_pickup_armorsmall_max;
274 self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
275 self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
276 self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
277 // precache weapon models/sounds
279 while (wep <= WEP_LAST)
281 weapon_action(wep, WR_PRECACHE);
286 makevectors (self.v_angle);
287 self.velocity = self.velocity + v_forward * 300;
290 self.velocity = self.velocity - v_forward * 300;
293 if(self.waypointsprite_deployed_personal)
295 self.speedrunning = TRUE;
296 tracebox(self.waypointsprite_deployed_personal.origin, self.mins, self.maxs, self.waypointsprite_deployed_personal.origin, MOVE_WORLDONLY, self);
299 sprint(self, "Cannot move there, cheater - only waypoints set using g_waypointsprite_personal work\n");
303 // Abort speedrun, teleport back
304 setorigin(self, self.waypointsprite_deployed_personal.origin);
305 self.oldvelocity = self.velocity = self.personal_velocity;
306 self.angles = self.personal_v_angle;
307 self.fixangle = TRUE;
310 bprint("The ", self.flagcarried.netname, " was returned to base by its carrier\n");
311 ReturnFlag(self.flagcarried);
314 self.ammo_rockets = 999;
315 self.ammo_nails = 999;
316 self.ammo_cells = 999;
317 self.ammo_shells = 999;
318 self.health = start_health;
319 self.armorvalue = start_armorvalue;
320 self.items |= itemsInMap & (IT_LASER | IT_SHOTGUN | IT_UZI | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER);
321 self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
322 self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
323 self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
325 else if(self.deadflag != DEAD_NO)
326 sprint(self, "UR DEAD AHAHAH))\n");
328 sprint(self, "No waypoint set, cheater (use g_waypointsprite_personal to set one)\n");
335 good = DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP;
336 evil = DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER;
337 evilsurf = Q3SURFACEFLAG_SKY;
339 m = self.dphitcontentsmask;
340 self.dphitcontentsmask = good | evil;
343 delta = world.maxs - world.mins;
345 maxattempts = ((sv_cheats >= 2) ? 100000 : 100);
347 for(i = 0; i < maxattempts; ++i)
349 start_x = org_x + random() * delta_x;
350 start_y = org_y + random() * delta_y;
351 start_z = org_z + random() * delta_z;
353 // rule 1: start inside world bounds, and outside
354 // solid, and don't start from somewhere where you can
356 tracebox(start, self.mins, self.maxs, start - '0 0 1' * delta_z, MOVE_NORMAL, self);
357 if(trace_fraction >= 1)
361 dprint("hit contents ", ftos(trace_dphitcontents), "\n");
362 if(trace_dphitcontents & evil)
364 if(trace_dphitq3surfaceflags & evilsurf)
367 // rule 2: if we are too high, lower the point
368 if(trace_fraction * delta_z > 1024)
369 start = trace_endpos + '0 0 1024';
370 enddown = trace_endpos;
372 // these can be traceLINES as we already verified the starting box
373 traceline(start, start + '1 0 0' * delta_x, MOVE_NORMAL, self);
374 if(trace_fraction >= 1)
376 traceline(start, start - '1 0 0' * delta_x, MOVE_NORMAL, self);
377 if(trace_fraction >= 1)
379 traceline(start, start + '0 1 0' * delta_y, MOVE_NORMAL, self);
380 if(trace_fraction >= 1)
382 traceline(start, start - '0 1 0' * delta_y, MOVE_NORMAL, self);
383 if(trace_fraction >= 1)
385 traceline(start, start + '0 0 1' * delta_z, MOVE_NORMAL, self);
386 if(trace_fraction >= 1)
389 end_x = org_x + random() * delta_x;
390 end_y = org_y + random() * delta_y;
391 end_z = org_z + random() * delta_z;
392 end = start + normalize(end - start) * vlen(delta);
394 // rule 3: start TO end must not be too short
395 tracebox(start, self.mins, self.maxs, end, MOVE_NORMAL, self);
398 if(trace_fraction < 256 / vlen(delta))
401 // rule 4: don't want to look at sky
402 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
405 // rule 5: we must not end up in trigger_hurt
406 if(tracebox_hits_trigger_hurt(start, self.mins, self.maxs, enddown))
408 dprint("trigger_hurt! ouch! and nothing else could find it!\n");
418 self.angles = vectoangles(end - start);
419 self.angles_x = -self.angles_x;
420 self.fixangle = TRUE;
421 self.velocity = '0 0 0';
422 dprint("Needed ", ftos(i + 1), " attempts\n");
425 sprint(self, "Emergency teleport could not find a good location, forget it!\n");
427 self.dphitcontentsmask = m;
430 makevectors(self.v_angle);
431 traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * MAX_SHOT_DISTANCE, FALSE, self);
432 if (trace_fraction < 1)
433 printsurfaceinfo(trace_ent, trace_endpos);
436 makevectors(self.v_angle);
437 traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 65536, FALSE, self);
438 sprint(self, strcat("distance: ", ftos(fabs(vlen(trace_endpos - (self.origin + self.view_ofs)))), "\n"));
443 else if(imp >= 103 && imp <= 106)
445 if(cvar("g_waypointeditor"))
450 waypoint_schedulerelink(waypoint_spawn(self.origin, self.origin, 0));
453 e = navigation_findnearestwaypoint(self, FALSE);
458 waypoint_schedulerelinkall();
467 //TetrisImpulses(imp);