|
|
1.1 root 1:
2: void() T_MissileTouch;
3: void() info_player_start;
4: void(entity targ, entity attacker) ClientObituary;
5: void(entity inflictor, entity attacker, float damage, entity ignore, string dtype) T_RadiusDamage;
6:
7: /*SERVER
8: void() monster_death_use;
9: */
10:
11: //============================================================================
12:
13: /*
14: ============
15: CanDamage
16:
17: Returns true if the inflictor can directly damage the target. Used for
18: explosions and melee attacks.
19: ============
20: */
21: float(entity targ, entity inflictor) CanDamage =
22: {
23: // bmodels need special checking because their origin is 0,0,0
24: if (targ.movetype == MOVETYPE_PUSH)
25: {
26: traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
27: if (trace_fraction == 1)
28: return TRUE;
29: if (trace_ent == targ)
30: return TRUE;
31: return FALSE;
32: }
33:
34: traceline(inflictor.origin, targ.origin, TRUE, self);
35: if (trace_fraction == 1)
36: return TRUE;
37: traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
38: if (trace_fraction == 1)
39: return TRUE;
40: traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
41: if (trace_fraction == 1)
42: return TRUE;
43: traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
44: if (trace_fraction == 1)
45: return TRUE;
46: traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
47: if (trace_fraction == 1)
48: return TRUE;
49:
50: return FALSE;
51: };
52:
53:
54: /*
55: ============
56: Killed
57: ============
58: */
59: void(entity targ, entity attacker) Killed =
60: {
61: local entity oself;
62:
63: oself = self;
64: self = targ;
65:
66: if (self.health < -99)
67: self.health = -99; // don't let sbar look bad if a player
68:
69: if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
70: { // doors, triggers, etc
71: self.th_die ();
72: self = oself;
73: return;
74: }
75:
76: self.enemy = attacker;
77:
78: // bump the monster counter
79: if (self.flags & FL_MONSTER)
80: {
81: killed_monsters = killed_monsters + 1;
82: WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
83: }
84:
85: ClientObituary(self, attacker);
86:
87: self.takedamage = DAMAGE_NO;
88: self.touch = SUB_Null;
89: self.effects = 0;
90:
91: /*SERVER
92: monster_death_use();
93: */
94: self.th_die ();
95:
96: self = oself;
97: };
98:
99:
100: /*
101: ============
102: T_Damage
103:
104: The damage is coming from inflictor, but get mad at attacker
105: This should be the only function that ever reduces health.
106: ============
107: */
108: void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
109: {
110: local vector dir;
111: local entity oldself;
112: local float save;
113: local float take;
114: local string s;
115: local string attackerteam, targteam;
116:
117:
118: if (!targ.takedamage)
119: return;
120:
121: // used by buttons and triggers to set activator for target firing
122: damage_attacker = attacker;
123:
124:
125: // check for quad damage powerup on the attacker
126: if (attacker.super_damage_finished > time && inflictor.classname != "door")
127: if (deathmatch == 4)
128: damage = damage * 8;
129: else
130: damage = damage * 4;
131:
132: // save damage based on the target's armor level
133:
134: save = ceil(targ.armortype*damage);
135: if (save >= targ.armorvalue)
136: {
137: save = targ.armorvalue;
138: targ.armortype = 0; // lost all armor
139: targ.items = targ.items - (targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
140: }
141:
142: targ.armorvalue = targ.armorvalue - save;
143: take = ceil(damage-save);
144:
145: // add to the damage total for clients, which will be sent as a single
146: // message at the end of the frame
147: // FIXME: remove after combining shotgun blasts?
148: if (targ.flags & FL_CLIENT)
149: {
150: targ.dmg_take = targ.dmg_take + take;
151: targ.dmg_save = targ.dmg_save + save;
152: targ.dmg_inflictor = inflictor;
153: }
154:
155: damage_inflictor = inflictor;
156:
157:
158: // figure momentum add
159: if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
160: {
161: dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
162: dir = normalize(dir);
163: // Set kickback for smaller weapons
164: //Zoid -- use normal NQ kickback
165: // // Read: only if it's not yourself doing the damage
166: // if ( (damage < 60) & ((attacker.classname == "player") & (targ.classname == "player")) & ( attacker.netname != targ.netname))
167: // targ.velocity = targ.velocity + dir * damage * 11;
168: // else
169: // Otherwise, these rules apply to rockets and grenades
170: // for blast velocity
171: targ.velocity = targ.velocity + dir * damage * 8;
172:
173: // Rocket Jump modifiers
174: if ( (rj > 1) & ((attacker.classname == "player") & (targ.classname == "player")) & ( attacker.netname == targ.netname))
175: targ.velocity = targ.velocity + dir * damage * rj;
176:
177: }
178:
179:
180:
181: // check for godmode or invincibility
182: if (targ.flags & FL_GODMODE)
183: return;
184: if (targ.invincible_finished >= time)
185: {
186: if (self.invincible_sound < time)
187: {
188: sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
189: self.invincible_sound = time + 2;
190: }
191: return;
192: }
193:
194: // team play damage avoidance
195: //ZOID 12-13-96: self.team doesn't work in QW. Use keys
196: attackerteam = infokey(attacker, "team");
197: targteam = infokey(targ, "team");
198:
199: if ((teamplay == 1) && (targteam == attackerteam) &&
200: (attacker.classname == "player") && (attackerteam != "") &&
201: inflictor.classname !="door")
202: return;
203:
204: if ((teamplay == 3) && (targteam == attackerteam) &&
205: (attacker.classname == "player") && (attackerteam != "") &&
206: (targ != attacker)&& inflictor.classname !="door")
207: return;
208:
209: // do the damage
210: targ.health = targ.health - take;
211:
212: if (targ.health <= 0)
213: {
214: Killed (targ, attacker);
215: return;
216: }
217:
218: // react to the damage
219: oldself = self;
220: self = targ;
221:
222: /*SERVER
223: if ( (self.flags & FL_MONSTER) && attacker != world)
224: {
225: // get mad unless of the same class (except for soldiers)
226: if (self != attacker && attacker != self.enemy)
227: {
228: if ( (self.classname != attacker.classname)
229: || (self.classname == "monster_army" ) )
230: {
231: if (self.enemy.classname == "player")
232: self.oldenemy = self.enemy;
233: self.enemy = attacker;
234: FoundTarget ();
235: }
236: }
237: }
238: */
239: if (self.th_pain)
240: {
241: self.th_pain (attacker, take);
242: }
243:
244: self = oldself;
245: };
246:
247: /*
248: ============
249: T_RadiusDamage
250: ============
251: */
252: void(entity inflictor, entity attacker, float damage, entity ignore, string dtype) T_RadiusDamage =
253: {
254: local float points;
255: local entity head;
256: local vector org;
257:
258: head = findradius(inflictor.origin, damage+40);
259:
260: while (head)
261: {
262: //bprint (PRINT_HIGH, head.classname);
263: //bprint (PRINT_HIGH, " | ");
264: //bprint (PRINT_HIGH, head.netname);
265: //bprint (PRINT_HIGH, "\n");
266:
267: if (head != ignore)
268: {
269: if (head.takedamage)
270: {
271: org = head.origin + (head.mins + head.maxs)*0.5;
272: points = 0.5*vlen (inflictor.origin - org);
273: if (points < 0)
274: points = 0;
275: points = damage - points;
276:
277: if (head == attacker)
278: points = points * 0.5;
279: if (points > 0)
280: {
281: if (CanDamage (head, inflictor))
282: {
283: head.deathtype = dtype;
284: T_Damage (head, inflictor, attacker, points);
285: }
286: }
287: }
288: }
289: head = head.chain;
290: }
291: };
292:
293: /*
294: ============
295: T_BeamDamage
296: ============
297: */
298: void(entity attacker, float damage) T_BeamDamage =
299: {
300: local float points;
301: local entity head;
302:
303: head = findradius(attacker.origin, damage+40);
304:
305: while (head)
306: {
307: if (head.takedamage)
308: {
309: points = 0.5*vlen (attacker.origin - head.origin);
310: if (points < 0)
311: points = 0;
312: points = damage - points;
313: if (head == attacker)
314: points = points * 0.5;
315: if (points > 0)
316: {
317: if (CanDamage (head, attacker))
318: T_Damage (head, attacker, attacker, points);
319: }
320: }
321: head = head.chain;
322: }
323: };
324:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.