|
|
1.1 root 1: #include "g_local.h"
2:
3: //void plat_CalcMove (edict_t *ent, vec3_t dest, void(*func)(edict_t*));
4: void Move_Calc (edict_t *ent, vec3_t dest, void(*func)(edict_t*));
5:
6: void fd_secret_move1(edict_t *self);
7: void fd_secret_move2(edict_t *self);
8: void fd_secret_move3(edict_t *self);
9: void fd_secret_move4(edict_t *self);
10: void fd_secret_move5(edict_t *self);
11: void fd_secret_move6(edict_t *self);
12: void fd_secret_done(edict_t *self);
13:
14: /*
15: =============================================================================
16:
17: SECRET DOORS
18:
19: =============================================================================
20: */
21:
22: #define SEC_OPEN_ONCE 1 // stays open
23: #define SEC_1ST_LEFT 2 // 1st move is left of arrow
24: #define SEC_1ST_DOWN 4 // 1st move is down from arrow
25: #define SEC_NO_SHOOT 8 // only opened by trigger
26: #define SEC_YES_SHOOT 16 // shootable even if targeted
27: #define SEC_MOVE_RIGHT 32
28: #define SEC_MOVE_FORWARD 64
29:
30: void fd_secret_use (edict_t *self, edict_t *other, edict_t *activator)
31: {
32: edict_t *ent;
33:
34: // gi.dprintf("fd_secret_use\n");
35: if (self->flags & FL_TEAMSLAVE)
36: return;
37:
38: // trigger all paired doors
39: for (ent = self ; ent ; ent = ent->teamchain)
40: Move_Calc(ent, ent->moveinfo.start_origin, fd_secret_move1);
41:
42: }
43:
44: void fd_secret_killed (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
45: {
46: // gi.dprintf("fd_secret_killed\n");
47: self->health = self->max_health;
48: self->takedamage = DAMAGE_NO;
49:
50: if (self->flags & FL_TEAMSLAVE && self->teammaster && self->teammaster->takedamage != DAMAGE_NO)
51: fd_secret_killed (self->teammaster, inflictor, attacker, damage, point);
52: else
53: fd_secret_use (self, inflictor, attacker);
54: }
55:
56: // Wait after first movement...
57: void fd_secret_move1(edict_t *self)
58: {
59: // gi.dprintf("fd_secret_move1\n");
60: self->nextthink = level.time + 1.0;
61: self->think = fd_secret_move2;
62: }
63:
64: // Start moving sideways w/sound...
65: void fd_secret_move2(edict_t *self)
66: {
67: // gi.dprintf("fd_secret_move2\n");
68: Move_Calc(self, self->moveinfo.end_origin, fd_secret_move3);
69: }
70:
71: // Wait here until time to go back...
72: void fd_secret_move3(edict_t *self)
73: {
74: // gi.dprintf("fd_secret_move3\n");
75: if (!(self->spawnflags & SEC_OPEN_ONCE))
76: {
77: self->nextthink = level.time + self->wait;
78: self->think = fd_secret_move4;
79: }
80: }
81:
82: // Move backward...
83: void fd_secret_move4(edict_t *self)
84: {
85: // gi.dprintf("fd_secret_move4\n");
86: Move_Calc(self, self->moveinfo.start_origin, fd_secret_move5);
87: }
88:
89: // Wait 1 second...
90: void fd_secret_move5(edict_t *self)
91: {
92: // gi.dprintf("fd_secret_move5\n");
93: self->nextthink = level.time + 1.0;
94: self->think = fd_secret_move6;
95: }
96:
97: void fd_secret_move6(edict_t *self)
98: {
99: // gi.dprintf("fd_secret_move6\n");
100: Move_Calc(self, self->move_origin, fd_secret_done);
101: }
102:
103: void fd_secret_done(edict_t *self)
104: {
105: // gi.dprintf("fd_secret_done\n");
106: if (!self->targetname || self->spawnflags & SEC_YES_SHOOT)
107: {
108: self->health = 1;
109: self->takedamage = DAMAGE_YES;
110: self->die = fd_secret_killed;
111: }
112: }
113:
114: void secret_blocked(edict_t *self, edict_t *other)
115: {
116: if (!(self->flags & FL_TEAMSLAVE))
117: T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 0, 0, MOD_CRUSH);
118:
119: // if (time < self->attack_finished)
120: // return;
121: // self->attack_finished = time + 0.5;
122: // T_Damage (other, self, self, self->dmg);
123: }
124:
125: /*
126: ================
127: secret_touch
128:
129: Prints messages
130: ================
131: */
132: void secret_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
133: {
134: if (other->health <= 0)
135: return;
136:
137: if (!(other->client))
138: return;
139:
140: if (self->monsterinfo.attack_finished > level.time)
141: return;
142:
143: self->monsterinfo.attack_finished = level.time + 2;
144:
145: if (self->message)
146: {
147: gi.centerprintf (other, self->message);
148: // fixme - put this sound back??
149: // gi.sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
150: }
151: }
152:
153:
154: /*QUAKED func_door_secret2 (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot slide_right slide_forward
155: Basic secret door. Slides back, then to the left. Angle determines direction.
156:
157: FLAGS:
158: open_once = not implemented yet
159: 1st_left = 1st move is left/right of arrow
160: 1st_down = 1st move is forwards/backwards
161: no_shoot = not implemented yet
162: always_shoot = even if targeted, keep shootable
163: reverse_left = the sideways move will be to right of arrow
164: reverse_back = the to/fro move will be forward
165:
166: VALUES:
167: wait = # of seconds before coming back (5 default)
168: dmg = damage to inflict when blocked (2 default)
169:
170: */
171:
172: void SP_func_door_secret2 (edict_t *ent)
173: {
174: vec3_t forward,right,up;
175: float lrSize, fbSize;
176:
177: ent->moveinfo.sound_start = gi.soundindex ("doors/dr1_strt.wav");
178: ent->moveinfo.sound_middle = gi.soundindex ("doors/dr1_mid.wav");
179: ent->moveinfo.sound_end = gi.soundindex ("doors/dr1_end.wav");
180:
181: if (!ent->dmg)
182: ent->dmg = 2;
183:
184: AngleVectors(ent->s.angles, forward, right, up);
185: VectorCopy(ent->s.origin, ent->move_origin);
186: VectorCopy(ent->s.angles, ent->move_angles);
187:
188: G_SetMovedir (ent->s.angles, ent->movedir);
189: ent->movetype = MOVETYPE_PUSH;
190: ent->solid = SOLID_BSP;
191: gi.setmodel (ent, ent->model);
192:
193: if(ent->move_angles[1] == 0 || ent->move_angles[1] == 180)
194: {
195: lrSize = ent->size[1];
196: fbSize = ent->size[0];
197: }
198: else if(ent->move_angles[1] == 90 || ent->move_angles[1] == 270)
199: {
200: lrSize = ent->size[0];
201: fbSize = ent->size[1];
202: }
203: else
204: {
205: gi.dprintf("Secret door not at 0,90,180,270!\n");
206: }
207:
208: if(ent->spawnflags & SEC_MOVE_FORWARD)
209: VectorScale(forward, fbSize, forward);
210: else
211: {
212: VectorScale(forward, fbSize * -1 , forward);
213: }
214:
215: if(ent->spawnflags & SEC_MOVE_RIGHT)
216: VectorScale(right, lrSize, right);
217: else
218: {
219: VectorScale(right, lrSize * -1, right);
220: }
221:
222: if(ent->spawnflags & SEC_1ST_DOWN)
223: {
224: VectorAdd(ent->s.origin, forward, ent->moveinfo.start_origin);
225: VectorAdd(ent->moveinfo.start_origin, right, ent->moveinfo.end_origin);
226: }
227: else
228: {
229: VectorAdd(ent->s.origin, right, ent->moveinfo.start_origin);
230: VectorAdd(ent->moveinfo.start_origin, forward, ent->moveinfo.end_origin);
231: }
232:
233: ent->touch = secret_touch;
234: ent->blocked = secret_blocked;
235: ent->use = fd_secret_use;
236: ent->moveinfo.speed = 50;
237: ent->moveinfo.accel = 50;
238: ent->moveinfo.decel = 50;
239:
240: if (!ent->targetname || ent->spawnflags & SEC_YES_SHOOT)
241: {
242: ent->health = 1;
243: ent->max_health = ent->health;
244: ent->takedamage = DAMAGE_YES;
245: ent->die = fd_secret_killed;
246: }
247: if (!ent->wait)
248: ent->wait = 5; // 5 seconds before closing
249:
250: gi.linkentity(ent);
251: }
252:
253: // ==================================================
254:
255: #define FWALL_START_ON 1
256:
257: void force_wall_think(edict_t *self)
258: {
259: if(!self->wait)
260: {
261: gi.WriteByte (svc_temp_entity);
262: gi.WriteByte (TE_FORCEWALL);
263: gi.WritePosition (self->pos1);
264: gi.WritePosition (self->pos2);
265: gi.WriteByte (self->style);
266: gi.multicast (self->offset, MULTICAST_PVS);
267: }
268:
269: self->think = force_wall_think;
270: self->nextthink = level.time + 0.1;
271: }
272:
273: void force_wall_use (edict_t *self, edict_t *other, edict_t *activator)
274: {
275: if(!self->wait)
276: {
277: self->wait = 1;
278: self->think = NULL;
279: self->nextthink = 0;
280: self->solid = SOLID_NOT;
281: gi.linkentity( self );
282: }
283: else
284: {
285: self->wait = 0;
286: self->think = force_wall_think;
287: self->nextthink = level.time + 0.1;
288: self->solid = SOLID_BSP;
289: KillBox(self); // Is this appropriate?
290: gi.linkentity (self);
291: }
292: }
293:
294: /*QUAKED func_force_wall (1 0 1) ? start_on
295: A vertical particle force wall. Turns on and solid when triggered.
296: If someone is in the force wall when it turns on, they're telefragged.
297:
298: start_on - forcewall begins activated. triggering will turn it off.
299: style - color of particles to use.
300: 208: green, 240: red, 241: blue, 224: orange
301: */
302: void SP_func_force_wall(edict_t *ent)
303: {
304: gi.setmodel (ent, ent->model);
305:
306: ent->offset[0] = (ent->absmax[0] + ent->absmin[0]) / 2;
307: ent->offset[1] = (ent->absmax[1] + ent->absmin[1]) / 2;
308: ent->offset[2] = (ent->absmax[2] + ent->absmin[2]) / 2;
309:
310: ent->pos1[2] = ent->absmax[2];
311: ent->pos2[2] = ent->absmax[2];
312: if(ent->size[0] > ent->size[1])
313: {
314: ent->pos1[0] = ent->absmin[0];
315: ent->pos2[0] = ent->absmax[0];
316: ent->pos1[1] = ent->offset[1];
317: ent->pos2[1] = ent->offset[1];
318: }
319: else
320: {
321: ent->pos1[0] = ent->offset[0];
322: ent->pos2[0] = ent->offset[0];
323: ent->pos1[1] = ent->absmin[1];
324: ent->pos2[1] = ent->absmax[1];
325: }
326:
327: if(!ent->style)
328: ent->style = 208;
329:
330: ent->movetype = MOVETYPE_NONE;
331: ent->wait = 1;
332:
333: if(ent->spawnflags & FWALL_START_ON)
334: {
335: ent->solid = SOLID_BSP;
336: ent->think = force_wall_think;
337: ent->nextthink = level.time + 0.1;
338: }
339: else
340: ent->solid = SOLID_NOT;
341:
342: ent->use = force_wall_use;
343:
344: ent->svflags = SVF_NOCLIENT;
345:
346: gi.linkentity(ent);
347: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.