]> icculus.org git repositories - divverent/nexuiz.git/blob - attic/TeamNexuiz/game/gamec/tf_ball.c
moved navnodeedit & TeamNexuiz to attic
[divverent/nexuiz.git] / attic / TeamNexuiz / game / gamec / tf_ball.c
1 // MegaTF Ball and Goal\r
2 // By: Ambush (and DyerMaker?)\r
3 // Implemented into Team:Nexuiz by avirox\r
4 \r
5 float () CheckExistence;\r
6 .float last_used;\r
7 .entity lastplayer;\r
8 \r
9 void() BallTouch = \r
10 {\r
11         if (other.classname == "player" && self.last_used <= time)\r
12         {\r
13                 sound(self, 3, "ball/bounce_fall.wav", 0.8, TRUE);\r
14                 self.last_used = time + 0.3;\r
15         }\r
16         if (other.classname != "player")\r
17         {\r
18                 sound(self, TRUE, "ball/bounce_hit.wav", TRUE, TRUE);\r
19         }\r
20         if (other.classname == "player")\r
21         {\r
22                 makevectors(other.v_angle);\r
23                 self.velocity = other.velocity + v_forward * 100 + v_up * 200;\r
24                 //self.angles = -1 * (vectoangles (self.velocity));\r
25 //              v_forward_y = 0;\r
26 //              v_forward_z = 0;\r
27                 self.avelocity = -1 * ((v_forward * 250)/* + crandom() * v_right*/);\r
28                 self.lastplayer = other;\r
29         }\r
30 };\r
31 \r
32 void() BallCheck = \r
33 {\r
34         self.movetype = 10;\r
35         self.nextthink = time + 15;\r
36         self.effects = FALSE;\r
37 //      self.angles = vectoangles (self.velocity);\r
38 };\r
39 \r
40 void() ballstart = \r
41 {\r
42         if (CheckExistence() == FALSE)\r
43         {\r
44                 dremove(self);\r
45                 return;\r
46         }\r
47 };\r
48 \r
49 void() BallStart = \r
50 {\r
51         local entity te;\r
52         sound(self, 3, "ball/whistle.wav", TRUE, FALSE);\r
53         te = find(world, classname, "ballstart");\r
54         while (te)\r
55         {\r
56                 setorigin(self, te.origin);\r
57                 te = find(te, classname, "ballstart");\r
58         }\r
59         self.nextthink = time + 5;\r
60         self.think = BallCheck;\r
61         self.movetype = 10;\r
62         self.velocity_z = 40;\r
63 };\r
64 \r
65 void() ball = \r
66 {\r
67         if (CheckExistence() == FALSE)\r
68         {\r
69                 dremove(self);\r
70                 return;\r
71         }\r
72         precache_model("models/ball/ball.md3");\r
73         setmodel(self, "models/ball/ball.md3");\r
74         self.movetype = FALSE;\r
75         setsize(self, '-16 -16 -14', '16 16 10');\r
76         self.solid = TRUE;\r
77         self.touch = BallTouch;\r
78         self.classname = "ball";\r
79         self.think = BallCheck;\r
80         self.nextthink = time + 15;\r
81         self.oldorigin = self.origin;\r
82 //      self.angles = vectoangles (self.velocity);\r
83 };\r
84 \r
85 void() GoalTouch = \r
86 {\r
87         local entity te;\r
88         if (other.classname != "ball")\r
89         {\r
90                 return;\r
91         }\r
92         if (self.last_used > time)\r
93         {\r
94                 return;\r
95         }\r
96         sound(self, 3, "ball/goal.wav", TRUE, FALSE);\r
97         self.last_used = time + 10;\r
98         te = find(world, classname, "player");\r
99         while (te)\r
100         {\r
101                 if (self.team_no == 2)\r
102                 {\r
103                         CenterPrint2(te, "        ^3Score^7 for ^1Reds^7 by ", other.lastplayer.netname);\r
104                 }\r
105                 else\r
106                 {\r
107                         CenterPrint2(te, "        ^3Score^7 for ^4Blues^7 by ", other.lastplayer.netname);\r
108                 }\r
109                 if (te.team_no == self.team_no && self.team_no != FALSE)\r
110                 {\r
111                         te.real_frags = te.real_frags + self.frags;\r
112                         te.frags = te.frags + self.frags;\r
113                         te.health = te.max_health;\r
114                 }\r
115                 te = find(te, classname, "player");\r
116         }\r
117         other.nextthink = time + 10;\r
118         other.think = BallStart;\r
119         other.movetype = 9;\r
120         other.velocity_z = 40;\r
121         other.effects = self.team_no * 64;\r
122 };\r
123 \r
124 void() sandball_goal = \r
125 {\r
126         if (CheckExistence() == FALSE)\r
127         {\r
128                 dremove(self);\r
129                 return;\r
130         }\r
131         precache_model("progs/null.mdl");\r
132         precache_sound("ball/goal.wav");\r
133         precache_sound("ball/whistle.wav");\r
134         precache_sound("ball/bounce_fall.wav");\r
135         precache_sound("ball/bounce_hit.wav");\r
136         setmodel(self, "progs/null.mdl");\r
137         self.movetype = FALSE;\r
138         self.skin = self.team_no;\r
139         self.solid = TRUE;\r
140         setsize(self, '-35 -35 -14', '35 35 50');\r
141         self.effects = FALSE;\r
142         self.touch = GoalTouch;\r
143 };\r
144 \r
145 void() PuckTouch = \r
146 {\r
147         if (other.classname == "player" && self.last_used <= time)\r
148         {\r
149                 sound(self, 3, "ball/bounce_fall.wav", 0.8, TRUE);\r
150                 self.last_used = time + 0.3;\r
151         }\r
152         if (other.classname != "player")\r
153         {\r
154                 sound(self, TRUE, "ball/bounce_hit.wav", TRUE, TRUE);\r
155         }\r
156         if (other.classname == "player")\r
157         {\r
158                 makevectors(other.v_angle);\r
159                 self.velocity = other.velocity + v_forward * 100/* + v_up * 200*/;\r
160                 //self.angles = -1 * (vectoangles (self.velocity));\r
161                 v_forward_y = 0;\r
162                 v_forward_z = 0;\r
163                 self.avelocity = -1 * ((v_forward * 250) + crandom() * v_right);\r
164                 self.lastplayer = other;\r
165         }\r
166 };\r
167 \r
168 void() PuckCheck = \r
169 {\r
170         self.movetype = 10;\r
171         self.nextthink = time + 15;\r
172         self.effects = FALSE;\r
173 };\r
174 \r
175 void() puck = \r
176 {\r
177         if (CheckExistence() == FALSE)\r
178         {\r
179                 dremove(self);\r
180                 return;\r
181         }\r
182         precache_model("models/puck/puck.md3");\r
183         setmodel(self, "models/puck/puck.md3");\r
184         self.movetype = MOVETYPE_WALK;\r
185         setsize(self, '-16 -16 -14', '16 16 10');\r
186         self.solid = TRUE;\r
187         self.touch = PuckTouch;\r
188         self.classname = "ball";\r
189         self.think = PuckCheck;\r
190         self.nextthink = time + 15;\r
191         self.oldorigin = self.origin;\r
192 };\r
193 \r
194 \r
195 vector(vector ang) SUB_NormalizeAngles = \r
196 {\r
197         while (ang_x > 360)\r
198         {\r
199                 ang_x = ang_x - 360;\r
200         }\r
201         while (ang_x < FALSE)\r
202         {\r
203                 ang_x = ang_x + 360;\r
204         }\r
205         while (ang_y > 360)\r
206         {\r
207                 ang_y = ang_y - 360;\r
208         }\r
209         while (ang_y < FALSE)\r
210         {\r
211                 ang_y = ang_y + 360;\r
212         }\r
213         while (ang_z > 360)\r
214         {\r
215                 ang_z = ang_z - 360;\r
216         }\r
217         while (ang_z < FALSE)\r
218         {\r
219                 ang_z = ang_z + 360;\r
220         }\r
221         return ang;\r
222 };\r
223 \r
224 /*=======================================\r
225                         Rotate function for QuakeC\r
226                         by Hipnotic Interactive\r
227                                 ===================================*/\r
228 \r
229 .float rotate_type;\r
230 .float endtime;\r
231 .float duration;\r
232 .vector neworigin;\r
233 .vector rotate;\r
234 .string path;\r
235 .string event;\r
236 .string group;\r
237 \r
238 float START_ON = 1;  // flag. abe thinks right.\r
239 float TOGGLE = 1;    // flag. abe thinks right.\r
240 \r
241 float ROTATION = 1;\r
242 float ANGLES = 2;    // flag. from abe.\r
243 float STOP = 4;\r
244 float NO_ROTATE = 8;\r
245 \r
246 float VISIBLE = 1;\r
247 float DAMAGE = 2;\r
248 float TOUCH = 2;                // this one too.\r
249 float SET_DAMAGE = 4;   // i made this one up.\r
250 \r
251 float NONBLOCKING = 4;\r
252 \r
253 float STAYOPEN = 4;\r
254 \r
255 float OBJECT_MOVEWALL = 2;\r
256 float OBJECT_ROTATE = 3;\r
257 float STATE_SPEEDINGUP = 4;\r
258 float STATE_ACTIVE = 5;\r
259 float OBJECT_SETORIGIN = 6;\r
260 float STATE_WAIT = 7;\r
261 float STATE_SLOWINGDOWN = 8;\r
262 float STATE_INACTIVE = 9;\r
263 float STATE_OPENING = 10;\r
264 float STATE_CLOSING = 11;\r
265 float STATE_MOVE = 12;\r
266 float STATE_STOP = 13;\r
267 float STATE_NEXT = 14;\r
268 float STATE_FIND = 15;\r
269 float STATE_OPEN = 16;\r
270 float STATE_CLOSED = 17;\r
271 \r
272 .vector dest;\r
273 \r
274 void() rotate_train_find;\r
275 void() rotate_door_group_reversedirection;\r
276 void() rotate_train_next;\r
277 \r
278 void() info_rotate = \r
279 {\r
280         self.nextthink = time + 2;\r
281         self.think = SUB_Remove;\r
282 };\r
283 \r
284 void() RotateTargets = \r
285 {\r
286         local entity ent;\r
287         local vector vx;\r
288         local vector vy;\r
289         local vector vz;\r
290         local vector org;\r
291         makevectors(self.angles);\r
292         ent = find(world, targetname, self.target);\r
293         while (ent)\r
294         {\r
295                 if (ent.rotate_type == OBJECT_SETORIGIN)\r
296                 {\r
297                         org = ent.oldorigin;\r
298                         vx = v_forward * org_x;\r
299                         vy = v_right * org_y;\r
300                         vy = vy * -1;\r
301                         vz = v_up * org_z;\r
302                         ent.neworigin = vx + vy + vz;\r
303                         setorigin(ent, ent.neworigin + self.origin);\r
304                 }\r
305                 else\r
306                 {\r
307                         if (ent.rotate_type == OBJECT_ROTATE)\r
308                         {\r
309                                 ent.angles = self.angles;\r
310                                 org = ent.oldorigin;\r
311                                 vx = v_forward * org_x;\r
312                                 vy = v_right * org_y;\r
313                                 vy = vy * -1;\r
314                                 vz = v_up * org_z;\r
315                                 ent.neworigin = vx + vy + vz;\r
316                                 setorigin(ent, ent.neworigin + self.origin);\r
317                         }\r
318                         else\r
319                         {\r
320                                 org = ent.oldorigin;\r
321                                 vx = v_forward * org_x;\r
322                                 vy = v_right * org_y;\r
323                                 vy = vy * -1;\r
324                                 vz = v_up * org_z;\r
325                                 ent.neworigin = vx + vy + vz;\r
326                                 ent.neworigin = self.origin - self.oldorigin + (ent.neworigin - ent.oldorigin);\r
327                                 ent.velocity = (ent.neworigin - ent.origin) * 25;\r
328                         }\r
329                 }\r
330                 ent = find(ent, targetname, self.target);\r
331         }\r
332 };\r
333 \r
334 void() RotateTargetsFinal = \r
335 {\r
336         local entity ent;\r
337         ent = find(world, targetname, self.target);\r
338         while (ent)\r
339         {\r
340                 ent.velocity = '0 0 0';\r
341                 if (ent.rotate_type == OBJECT_ROTATE)\r
342                 {\r
343                         ent.angles = self.angles;\r
344                 }\r
345                 ent = find(ent, targetname, self.target);\r
346         }\r
347 };\r
348 \r
349 void() SetTargetOrigin = \r
350 {\r
351         local entity ent;\r
352         ent = find(world, targetname, self.target);\r
353         while (ent)\r
354         {\r
355                 if (ent.rotate_type == OBJECT_MOVEWALL)\r
356                 {\r
357                         setorigin(ent, self.origin - self.oldorigin + (ent.neworigin - ent.oldorigin));\r
358                 }\r
359                 else\r
360                 {\r
361                         setorigin(ent, ent.neworigin + self.origin);\r
362                 }\r
363                 ent = find(ent, targetname, self.target);\r
364         }\r
365 };\r
366 \r
367 void() LinkRotateTargets = \r
368 {\r
369         local entity ent;\r
370         local vector tempvec;\r
371         self.oldorigin = self.origin;\r
372         ent = find(world, targetname, self.target);\r
373         while (ent)\r
374         {\r
375                 if (ent.classname == "rotate_object")\r
376                 {\r
377                         ent.rotate_type = OBJECT_ROTATE;\r
378                         ent.oldorigin = ent.origin - self.oldorigin;\r
379                         ent.neworigin = ent.origin - self.oldorigin;\r
380                         ent.owner = self;\r
381                 }\r
382                 else\r
383                 {\r
384                         if (ent.classname == "func_movewall")\r
385                         {\r
386                                 ent.rotate_type = OBJECT_MOVEWALL;\r
387                                 tempvec = (ent.absmin + ent.absmax) * 0.5;\r
388                                 ent.oldorigin = tempvec - self.oldorigin;\r
389                                 ent.neworigin = ent.oldorigin;\r
390                                 ent.owner = self;\r
391                         }\r
392                         else\r
393                         {\r
394                                 ent.rotate_type = OBJECT_SETORIGIN;\r
395                                 ent.oldorigin = ent.origin - self.oldorigin;\r
396                                 ent.neworigin = ent.origin - self.oldorigin;\r
397                         }\r
398                 }\r
399                 ent = find(ent, targetname, self.target);\r
400         }\r
401 };\r
402 \r
403 void(float amount) SetDamageOnTargets = \r
404 {\r
405         local entity ent;\r
406         ent = find(world, targetname, self.target);\r
407         while (ent)\r
408         {\r
409                 if (ent.classname == "func_movewall")\r
410                 {\r
411                         ent.dmg = amount;\r
412                 }\r
413                 ent = find(ent, targetname, self.target);\r
414         }\r
415 };\r
416 \r
417 void() rotate_entity_think = \r
418 {\r
419         local float t;\r
420         t = time - self.ltime;\r
421         self.ltime = time;\r
422         if (self.state == STATE_SPEEDINGUP)\r
423         {\r
424                 self.count = self.count + self.cnt * t;\r
425                 if (self.count > TRUE)\r
426                 {\r
427                         self.count = TRUE;\r
428                 }\r
429                 t = t * self.count;\r
430         }\r
431         else\r
432         {\r
433                 if (self.state == STATE_SLOWINGDOWN)\r
434                 {\r
435                         self.count = self.count - self.cnt * t;\r
436                         if (self.count < FALSE)\r
437                         {\r
438                                 RotateTargetsFinal();\r
439                                 self.state = STATE_INACTIVE;\r
440                                 self.think = SUB_Null;\r
441                                 return;\r
442                         }\r
443                         t = t * self.count;\r
444                 }\r
445         }\r
446         self.angles = self.angles + self.rotate * t;\r
447         self.angles = SUB_NormalizeAngles(self.angles);\r
448         RotateTargets();\r
449         self.nextthink = time + 0.020000;\r
450 };\r
451 \r
452 void() rotate_entity_use = \r
453 {\r
454         self.frame = TRUE - self.frame;\r
455         if (self.state == STATE_ACTIVE)\r
456         {\r
457                 if (self.spawnflags & TOGGLE)\r
458                 {\r
459                         if (self.speed)\r
460                         {\r
461                                 self.count = TRUE;\r
462                                 self.state = STATE_SLOWINGDOWN;\r
463                         }\r
464                         else\r
465                         {\r
466                                 self.state = STATE_INACTIVE;\r
467                                 self.think = SUB_Null;\r
468                         }\r
469                 }\r
470         }\r
471         else\r
472         {\r
473                 if (self.state == STATE_INACTIVE)\r
474                 {\r
475                         self.think = rotate_entity_think;\r
476                         self.nextthink = time + 0.020000;\r
477                         self.ltime = time;\r
478                         if (self.speed)\r
479                         {\r
480                                 self.count = FALSE;\r
481                                 self.state = STATE_SPEEDINGUP;\r
482                         }\r
483                         else\r
484                         {\r
485                                 self.state = STATE_ACTIVE;\r
486                         }\r
487                 }\r
488                 else\r
489                 {\r
490                         if (self.state == STATE_SPEEDINGUP)\r
491                         {\r
492                                 if (self.spawnflags & TOGGLE)\r
493                                 {\r
494                                         self.state = STATE_SLOWINGDOWN;\r
495                                 }\r
496                         }\r
497                         else\r
498                         {\r
499                                 self.state = STATE_SPEEDINGUP;\r
500                         }\r
501                 }\r
502         }\r
503 };\r
504 \r
505 void() rotate_entity_firstthink = \r
506 {\r
507         LinkRotateTargets();\r
508         if (self.spawnflags & START_ON)\r
509         {\r
510                 self.state = STATE_ACTIVE;\r
511                 self.think = rotate_entity_think;\r
512                 self.nextthink = time + 0.020000;\r
513                 self.ltime = time;\r
514         }\r
515         else\r
516         {\r
517                 self.state = STATE_INACTIVE;\r
518                 self.think = SUB_Null;\r
519         }\r
520         self.use = rotate_entity_use;\r
521 };\r
522 \r
523 /*QUAKED func_rotate_entity (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE START_ON\r
524 Creates an entity that continually rotates.  Can be toggled on and\r
525 off if targeted.\r
526 \r
527 TOGGLE = allows the rotation to be toggled on/off\r
528 \r
529 START_ON = wether the entity is spinning when spawned.  If TOGGLE is 0, entity can be turned on, but not off.\r
530 \r
531 If "deathtype" is set with a string, this is the message that will appear when a player is killed by the train.\r
532 \r
533 "rotate" is the rate to rotate.\r
534 "target" is the center of rotation.\r
535 "speed"  is how long the entity takes to go from standing still to full speed and vice-versa.\r
536 */\r
537 \r
538 void() func_rotate_entity = \r
539 {\r
540         self.solid = FALSE;\r
541         self.movetype = FALSE;\r
542         setmodel(self, self.model);\r
543         setsize(self, self.mins, self.maxs);\r
544         if (self.speed != FALSE)\r
545         {\r
546                 self.cnt = TRUE / self.speed;\r
547         }\r
548         self.think = rotate_entity_firstthink;\r
549         self.nextthink = time + 0.1;\r
550         self.ltime = time;\r
551 };\r
552 \r
553 /*QUAKED path_rotate (0.5 0.3 0) (-8 -8 -8) (8 8 8) ROTATION ANGLES STOP NO_ROTATE DAMAGE MOVETIME SET_DAMAGE\r
554  Path for rotate_train.\r
555 \r
556  ROTATION tells train to rotate at rate specified by "rotate".  Use '0 0 0' to stop rotation.\r
557 \r
558  ANGLES tells train to rotate to the angles specified by "angles" while traveling to this path_rotate.  Use values < 0 or > 360 to guarantee that it turns in a certain direction.  Having this flag set automatically clears any rotation.\r
559 \r
560  STOP tells the train to stop and wait to be retriggered.\r
561 \r
562  NO_ROTATE tells the train to stop rotating when waiting to be triggered.\r
563 \r
564  DAMAGE tells the train to cause damage based on "dmg".\r
565 \r
566  MOVETIME tells the train to interpret "speed" as the length of time to take moving from one corner to another.\r
567 \r
568  SET_DAMAGE tells the train to set all targets damage to "dmg"\r
569 \r
570  "noise" contains the name of the sound to play when train stops.\r
571  "noise1" contains the name of the sound to play when train moves.\r
572  "event" is a target to trigger when train arrives at path_rotate.\r
573 */\r
574 \r
575 void() path_rotate = \r
576 {\r
577         if (self.noise)\r
578         {\r
579                 precache_sound(self.noise);\r
580         }\r
581         if (self.noise1)\r
582         {\r
583                 precache_sound(self.noise1);\r
584         }\r
585 };\r
586 \r
587 void() rotate_train_think = \r
588 {\r
589         local float t;\r
590         local float timeelapsed;\r
591         t = time - self.ltime;\r
592         self.ltime = time;\r
593         if (self.endtime && time >= self.endtime)\r
594         {\r
595                 self.endtime = FALSE;\r
596                 if (self.state == STATE_MOVE)\r
597                 {\r
598                         setorigin(self, self.finaldest);\r
599                         self.velocity = '0 0 0';\r
600                 }\r
601                 if (self.think1)\r
602                 {\r
603                         self.think1();\r
604                 }\r
605         }\r
606         else\r
607         {\r
608                 timeelapsed = (time - self.cnt) * self.duration;\r
609                 if (timeelapsed > TRUE)\r
610                 {\r
611                         timeelapsed = TRUE;\r
612                 }\r
613                 setorigin(self, self.dest1 + self.dest2 * timeelapsed);\r
614         }\r
615         self.angles = self.angles + self.rotate * t;\r
616         self.angles = SUB_NormalizeAngles(self.angles);\r
617         RotateTargets();\r
618         self.nextthink = time + 0.020000;\r
619 };\r
620 \r
621 void() rotate_train_use = \r
622 {\r
623         if (self.think1 != rotate_train_find)\r
624         {\r
625                 if (self.velocity != '0 0 0')\r
626                 {\r
627                         return;\r
628                 }\r
629                 if (self.think1)\r
630                 {\r
631                         self.think1();\r
632                 }\r
633         }\r
634 };\r
635 \r
636 void() rotate_train_wait = \r
637 {\r
638         self.state = STATE_WAIT;\r
639         if (self.goalentity.noise)\r
640         {\r
641                 if (self.goalentity.noise == "ambience/chopper.wav")\r
642                 {\r
643                         sound(self, 2, self.goalentity.noise, TRUE, FALSE);\r
644                 }\r
645                 else\r
646                 {\r
647                         sound(self, 2, self.goalentity.noise, TRUE, TRUE);\r
648                 }\r
649         }\r
650         else\r
651         {\r
652                 sound(self, 2, self.noise, TRUE, TRUE);\r
653         }\r
654         if (self.goalentity.spawnflags & ANGLES)\r
655         {\r
656                 self.rotate = '0 0 0';\r
657                 self.angles = self.finalangle;\r
658         }\r
659         if (self.goalentity.spawnflags & NO_ROTATE)\r
660         {\r
661                 self.rotate = '0 0 0';\r
662         }\r
663         self.endtime = self.ltime + self.goalentity.wait;\r
664         self.think1 = rotate_train_next;\r
665 };\r
666 \r
667 void() rotate_train_stop = \r
668 {\r
669         self.state = STATE_STOP;\r
670         if (self.goalentity.noise)\r
671         {\r
672                 if (self.goalentity.noise == "ambience/chopper.wav")\r
673                 {\r
674                         sound(self, 2, self.goalentity.noise, TRUE, FALSE);\r
675                 }\r
676                 else\r
677                 {\r
678                         sound(self, 2, self.goalentity.noise, TRUE, TRUE);\r
679                 }\r
680         }\r
681         else\r
682         {\r
683                 sound(self, 2, self.noise, TRUE, TRUE);\r
684         }\r
685         if (self.goalentity.spawnflags & ANGLES)\r
686         {\r
687                 self.rotate = '0 0 0';\r
688                 self.angles = self.finalangle;\r
689         }\r
690         if (self.goalentity.spawnflags & NO_ROTATE)\r
691         {\r
692                 self.rotate = '0 0 0';\r
693         }\r
694         self.dmg = FALSE;\r
695         self.think1 = rotate_train_next;\r
696 };\r
697 \r
698 void() rotate_train_next = \r
699 {\r
700         local entity targ;\r
701         local entity current;\r
702         local vector vdestdelta;\r
703         local float len;\r
704         local float traveltime;\r
705         local float div;\r
706         local string temp;\r
707         self.state = STATE_NEXT;\r
708         current = self.goalentity;\r
709         targ = find(world, targetname, self.path);\r
710         if (targ.classname != "path_rotate")\r
711         {\r
712                 objerror("Next target is not path_rotate");\r
713         }\r
714         if (self.goalentity.noise1)\r
715         {\r
716                 self.noise1 = self.goalentity.noise1;\r
717         }\r
718         if (self.noise1 == "ambience/chopper.wav")\r
719         {\r
720                 sound(self, 2, self.noise1, TRUE, FALSE);\r
721         }\r
722         else\r
723         {\r
724                 sound(self, 2, self.noise1, TRUE, TRUE);\r
725         }\r
726         self.goalentity = targ;\r
727         self.path = targ.target;\r
728         if (!(self.path))\r
729         {\r
730                 objerror("rotate_train_next: no next target");\r
731         }\r
732         if (targ.spawnflags & STOP)\r
733         {\r
734                 self.think1 = rotate_train_stop;\r
735         }\r
736         else\r
737         {\r
738                 if (targ.wait)\r
739                 {\r
740                         self.think1 = rotate_train_wait;\r
741                 }\r
742                 else\r
743                 {\r
744                         self.think1 = rotate_train_next;\r
745                 }\r
746         }\r
747         if (current.event)\r
748         {\r
749                 temp = self.target;\r
750                 self.target = current.event;\r
751                 self.message = current.message;\r
752                 SUB_UseTargets();\r
753                 self.target = temp;\r
754                 self.message = string_null;\r
755         }\r
756         if (current.spawnflags & ANGLES)\r
757         {\r
758                 self.rotate = '0 0 0';\r
759                 self.angles = self.finalangle;\r
760         }\r
761         if (current.spawnflags & ROTATION)\r
762         {\r
763                 self.rotate = current.rotate;\r
764         }\r
765         if (current.spawnflags & DAMAGE)\r
766         {\r
767                 self.dmg = current.dmg;\r
768         }\r
769         if (current.spawnflags & SET_DAMAGE)\r
770         {\r
771                 SetDamageOnTargets(current.dmg);\r
772         }\r
773         if (current.speed == -1)\r
774         {\r
775                 setorigin(self, targ.origin);\r
776                 self.endtime = self.ltime + 0.010000;\r
777                 SetTargetOrigin();\r
778                 if (targ.spawnflags & ANGLES)\r
779                 {\r
780                         self.angles = targ.angles;\r
781                 }\r
782                 self.duration = TRUE;\r
783                 self.cnt = time;\r
784                 self.dest2 = '0 0 0';\r
785                 self.dest1 = self.origin;\r
786                 self.finaldest = self.origin;\r
787         }\r
788         else\r
789         {\r
790                 self.state = STATE_MOVE;\r
791                 self.finaldest = targ.origin;\r
792                 if (self.finaldest == self.origin)\r
793                 {\r
794                         self.velocity = '0 0 0';\r
795                         self.endtime = self.ltime + 0.1;\r
796                         self.duration = TRUE;\r
797                         self.cnt = time;\r
798                         self.dest2 = '0 0 0';\r
799                         self.dest1 = self.origin;\r
800                         self.finaldest = self.origin;\r
801                         return;\r
802                 }\r
803                 vdestdelta = self.finaldest - self.origin;\r
804                 len = vlen(vdestdelta);\r
805 //              if (current.spawnflags & MOVETIME)\r
806 //              {\r
807 //                      traveltime = current.speed;\r
808 //              }\r
809 //              else\r
810 //              {\r
811                         if (current.speed > FALSE)\r
812                         {\r
813                                 self.speed = current.speed;\r
814                         }\r
815                         if (!(self.speed))\r
816                         {\r
817                                 objerror("No speed is defined!");\r
818                         }\r
819                         traveltime = len / self.speed;\r
820 //              }\r
821                 if (traveltime < 0.1)\r
822                 {\r
823                         self.velocity = '0 0 0';\r
824                         self.endtime = self.ltime + 0.1;\r
825                         if (targ.spawnflags & ANGLES)\r
826                         {\r
827                                 self.angles = targ.angles;\r
828                         }\r
829                         return;\r
830                 }\r
831                 div = TRUE / traveltime;\r
832                 if (targ.spawnflags & ANGLES)\r
833                 {\r
834                         self.finalangle = SUB_NormalizeAngles(targ.angles);\r
835                         self.rotate = (targ.angles - self.angles) * div;\r
836                 }\r
837                 self.endtime = self.ltime + traveltime;\r
838                 self.velocity = vdestdelta * div;\r
839                 self.duration = div;\r
840                 self.cnt = time;\r
841                 self.dest2 = vdestdelta;\r
842                 self.dest1 = self.origin;\r
843         }\r
844 };\r
845 \r
846 void() rotate_train_find = \r
847 {\r
848         local entity targ;\r
849         self.state = STATE_FIND;\r
850         LinkRotateTargets();\r
851         targ = find(world, targetname, self.path);\r
852         if (targ.classname != "path_rotate")\r
853         {\r
854                 objerror("Next target is not path_rotate");\r
855         }\r
856         self.goalentity = targ;\r
857         if (targ.spawnflags & ANGLES)\r
858         {\r
859                 self.angles = targ.angles;\r
860                 self.finalangle = SUB_NormalizeAngles(targ.angles);\r
861         }\r
862         self.path = targ.target;\r
863         setorigin(self, targ.origin);\r
864         SetTargetOrigin();\r
865         RotateTargetsFinal();\r
866         self.think1 = rotate_train_next;\r
867         if (!(self.targetname))\r
868         {\r
869                 self.endtime = self.ltime + 0.1;\r
870         }\r
871         else\r
872         {\r
873                 self.endtime = FALSE;\r
874         }\r
875         self.duration = TRUE;\r
876         self.cnt = time;\r
877         self.dest2 = '0 0 0';\r
878         self.dest1 = self.origin;\r
879 };\r
880 \r
881 void() func_rotate_train = \r
882 {\r
883         if (!(self.speed))\r
884         {\r
885                 self.speed = 100;\r
886         }\r
887         if (!(self.target))\r
888         {\r
889                 objerror("rotate_train without a target");\r
890         }\r
891         if (!(self.noise))\r
892         {\r
893                 if (self.sounds == FALSE)\r
894                 {\r
895                         self.noise = "misc/null.wav";\r
896                 }\r
897                 if (self.sounds == TRUE)\r
898                 {\r
899                         self.noise = "plats/train2.wav";\r
900                 }\r
901         }\r
902         if (!(self.noise1))\r
903         {\r
904                 if (self.sounds == FALSE)\r
905                 {\r
906                         self.noise1 = "misc/null.wav";\r
907                 }\r
908                 if (self.sounds == TRUE)\r
909                 {\r
910                         self.noise1 = "plats/train1.wav";\r
911                 }\r
912         }\r
913         precache_sound(self.noise);\r
914         precache_sound(self.noise1);\r
915         self.cnt = TRUE;\r
916         self.solid = FALSE;\r
917         self.movetype = 4;\r
918         self.use = rotate_train_use;\r
919         setmodel(self, self.model);\r
920         setsize(self, self.mins, self.maxs);\r
921         setorigin(self, self.origin);\r
922         self.ltime = time;\r
923         self.nextthink = self.ltime + 0.1;\r
924         self.endtime = self.ltime + 0.1;\r
925         self.think = rotate_train_think;\r
926         self.think1 = rotate_train_find;\r
927         self.state = STATE_FIND;\r
928         self.duration = TRUE;\r
929         self.cnt = 0.1;\r
930         self.dest2 = '0 0 0';\r
931         self.dest1 = self.origin;\r
932         self.flags = self.flags | 512;\r
933 };\r
934 \r
935 void() movewall_touch = \r
936 {\r
937         if (time < self.owner.attack_finished)\r
938         {\r
939                 return;\r
940         }\r
941         if (self.dmg)\r
942         {\r
943                 T_Damage(other, self, self.owner, self.dmg);\r
944                 self.owner.attack_finished = time + 0.5;\r
945         }\r
946         else\r
947         {\r
948                 if (self.owner.dmg)\r
949                 {\r
950                         T_Damage(other, self, self.owner, self.owner.dmg);\r
951                         self.owner.attack_finished = time + 0.5;\r
952                 }\r
953         }\r
954 };\r
955 \r
956 void() movewall_blocked = \r
957 {\r
958         local entity temp;\r
959         if (time < self.owner.attack_finished)\r
960         {\r
961                 return;\r
962         }\r
963         self.owner.attack_finished = time + 0.5;\r
964         if (self.owner.classname == "func_rotate_door")\r
965         {\r
966                 temp = self;\r
967                 self = self.owner;\r
968                 rotate_door_group_reversedirection();\r
969                 self = temp;\r
970         }\r
971         if (self.dmg)\r
972         {\r
973                 T_Damage(other, self, self.owner, self.dmg);\r
974                 self.owner.attack_finished = time + 0.5;\r
975         }\r
976         else\r
977         {\r
978                 if (self.owner.dmg)\r
979                 {\r
980                         T_Damage(other, self, self.owner, self.owner.dmg);\r
981                         self.owner.attack_finished = time + 0.5;\r
982                 }\r
983         }\r
984 };\r
985 \r
986 void() movewall_think = \r
987 {\r
988         self.ltime = time;\r
989         self.nextthink = time + 0.020000;\r
990 };\r
991 \r
992 void() func_movewall = \r
993 {\r
994         self.angles = '0 0 0';\r
995         self.movetype = 7;\r
996         if (self.spawnflags & NONBLOCKING)\r
997         {\r
998                 self.solid = FALSE;\r
999         }\r
1000         else\r
1001         {\r
1002                 self.solid = 4;\r
1003                 self.blocked = movewall_blocked;\r
1004         }\r
1005         if (self.spawnflags & TOUCH)\r
1006         {\r
1007                 self.touch = movewall_touch;\r
1008         }\r
1009         setmodel(self, self.model);\r
1010         if (!(self.spawnflags & VISIBLE))\r
1011         {\r
1012                 self.model = string_null;\r
1013         }\r
1014         self.think = movewall_think;\r
1015         self.nextthink = time + 0.020000;\r
1016         self.ltime = time;\r
1017 };\r
1018 \r
1019 void() rotate_object = \r
1020 {\r
1021         self.classname = "rotate_object";\r
1022         self.solid = FALSE;\r
1023         self.movetype = FALSE;\r
1024         setmodel(self, self.model);\r
1025         setsize(self, self.mins, self.maxs);\r
1026         self.think = SUB_Null;\r
1027 };\r
1028 \r
1029 void() rotate_door_think2 = \r
1030 {\r
1031         local float t;\r
1032         t = time - self.ltime;\r
1033         self.ltime = time;\r
1034         self.frame = TRUE - self.frame;\r
1035         self.angles = self.dest;\r
1036         if (self.state == STATE_OPENING)\r
1037         {\r
1038                 self.state = STATE_OPEN;\r
1039         }\r
1040         else\r
1041         {\r
1042                 if (self.spawnflags & STAYOPEN)\r
1043                 {\r
1044                         rotate_door_group_reversedirection();\r
1045                         return;\r
1046                 }\r
1047                 self.state = STATE_CLOSED;\r
1048         }\r
1049         sound(self, 2, self.noise3, TRUE, TRUE);\r
1050         self.think = SUB_Null;\r
1051         RotateTargetsFinal();\r
1052 };\r
1053 \r
1054 void() rotate_door_think = \r
1055 {\r
1056         local float t;\r
1057         t = time - self.ltime;\r
1058         self.ltime = time;\r
1059         if (time < self.endtime)\r
1060         {\r
1061                 self.angles = self.angles + self.rotate * t;//self.angles = self.angles + self.rotate * t;\r
1062                 RotateTargets();\r
1063         }\r
1064         else\r
1065         {\r
1066                 self.angles = self.dest;\r
1067                 RotateTargets();\r
1068                 self.think = rotate_door_think2;\r
1069         }\r
1070         self.nextthink = time + 0.010000;\r
1071 };\r
1072 \r
1073 void() rotate_door_reversedirection = \r
1074 {\r
1075         local vector start;\r
1076         self.frame = TRUE - self.frame;\r
1077         if (self.state == STATE_CLOSING)\r
1078         {\r
1079                 start = self.dest1;\r
1080                 self.dest = self.dest2;\r
1081                 self.state = STATE_OPENING;\r
1082         }\r
1083         else\r
1084         {\r
1085                 start = self.dest2;\r
1086                 self.dest = self.dest1;\r
1087                 self.state = STATE_CLOSING;\r
1088         }\r
1089         sound(self, 2, self.noise2, TRUE, TRUE);\r
1090         self.rotate = (self.dest - start) * (TRUE / self.speed);\r
1091         self.think = rotate_door_think;\r
1092         self.nextthink = time + 0.020000;\r
1093         self.endtime = time + self.speed - (self.endtime - time);\r
1094         self.ltime = time;\r
1095 };\r
1096 \r
1097 void() rotate_door_group_reversedirection = \r
1098 {\r
1099         local string name;\r
1100         if (self.group)\r
1101         {\r
1102                 name = self.group;\r
1103                 self = find(world, group, name);\r
1104                 while (self)\r
1105                 {\r
1106                         rotate_door_reversedirection();\r
1107                         self = find(self, group, name);\r
1108                 }\r
1109         }\r
1110         else\r
1111         {\r
1112                 rotate_door_reversedirection();\r
1113         }\r
1114 };\r
1115 \r
1116 void() rotate_door_use = \r
1117 {\r
1118         local vector start;\r
1119         if (self.state != STATE_OPEN && self.state != STATE_CLOSED)\r
1120         {\r
1121                 return;\r
1122         }\r
1123         if (!(self.cnt))\r
1124         {\r
1125                 self.cnt = TRUE;\r
1126                 LinkRotateTargets();\r
1127         }\r
1128         self.frame = TRUE - self.frame;\r
1129         if (self.state == STATE_CLOSED)\r
1130         {\r
1131                 start = self.dest1;\r
1132                 self.dest = self.dest2;\r
1133                 self.state = STATE_OPENING;\r
1134         }\r
1135         else\r
1136         {\r
1137                 start = self.dest2;\r
1138                 self.dest = self.dest1;\r
1139                 self.state = STATE_CLOSING;\r
1140         }\r
1141         sound(self, 2, self.noise2, TRUE, TRUE);\r
1142         self.rotate = (self.dest - start) * (TRUE / self.speed);\r
1143         self.think = rotate_door_think;\r
1144         self.nextthink = time + 0.010000;\r
1145         self.endtime = time + self.speed;\r
1146         self.ltime = time;\r
1147 };\r
1148 \r
1149 void() func_rotate_door = \r
1150 {\r
1151         if (!(self.target))\r
1152         {\r
1153                 objerror("rotate_door without target.");\r
1154         }\r
1155         self.dest1 = '0 0 0';\r
1156         self.dest2 = self.angles;\r
1157         self.angles = self.dest1;\r
1158         if (!(self.speed))\r
1159         {\r
1160                 self.speed = 2;\r
1161         }\r
1162         self.cnt = FALSE;\r
1163         if (!(self.dmg))\r
1164         {\r
1165                 self.dmg = 2;\r
1166         }\r
1167         else\r
1168         {\r
1169                 if (self.dmg < FALSE)\r
1170                 {\r
1171                         self.dmg = FALSE;\r
1172                 }\r
1173         }\r
1174         if (self.sounds == FALSE)\r
1175         {\r
1176                 precache_sound("misc/null.wav");\r
1177                 if (self.noise1)\r
1178                 {\r
1179                         precache_sound(self.noise1);\r
1180                 }\r
1181                 else\r
1182                 {\r
1183                         self.noise1 = "misc/null.wav";\r
1184                 }\r
1185                 if (self.noise2)\r
1186                 {\r
1187                         precache_sound(self.noise2);\r
1188                 }\r
1189                 else\r
1190                 {\r
1191                         self.noise2 = "misc/null.wav";\r
1192                 }\r
1193                 if (self.noise3)\r
1194                 {\r
1195                         precache_sound(self.noise3);\r
1196                 }\r
1197                 else\r
1198                 {\r
1199                         self.noise3 = "misc/null.wav";\r
1200                 }\r
1201         }\r
1202         if (self.sounds == TRUE)\r
1203         {\r
1204                 precache_sound("doors/latch2.wav");\r
1205                 precache_sound("doors/winch2.wav");\r
1206                 precache_sound("doors/drclos4.wav");\r
1207                 self.noise1 = "doors/latch2.wav";\r
1208                 self.noise2 = "doors/winch2.wav";\r
1209                 self.noise3 = "doors/drclos4.wav";\r
1210         }\r
1211         if (self.sounds == 2)\r
1212         {\r
1213                 precache_sound("doors/airdoor1.wav");\r
1214                 precache_sound("doors/airdoor2.wav");\r
1215                 self.noise2 = "doors/airdoor1.wav";\r
1216                 self.noise1 = "doors/airdoor2.wav";\r
1217                 self.noise3 = "doors/airdoor2.wav";\r
1218         }\r
1219         if (self.sounds == 3)\r
1220         {\r
1221                 precache_sound("doors/basesec1.wav");\r
1222                 precache_sound("doors/basesec2.wav");\r
1223                 self.noise2 = "doors/basesec1.wav";\r
1224                 self.noise1 = "doors/basesec2.wav";\r
1225                 self.noise3 = "doors/basesec2.wav";\r
1226         }\r
1227         self.solid = FALSE;\r
1228         self.movetype = FALSE;\r
1229         setmodel(self, self.model);\r
1230         setorigin(self, self.origin);\r
1231         setsize(self, self.mins, self.maxs);\r
1232         self.state = STATE_CLOSED;\r
1233         self.use = rotate_door_use;\r
1234         self.think = SUB_Null;\r
1235 };\r
1236 \r