3
|
1 /*--------------------------------------------------------------------------
|
|
2 NETREK II -- Paradise
|
|
3
|
|
4 Permission to use, copy, modify, and distribute this software and its
|
|
5 documentation, or any derivative works thereof, for any NON-COMMERCIAL
|
|
6 purpose and without fee is hereby granted, provided that this copyright
|
|
7 notice appear in all copies. No representations are made about the
|
|
8 suitability of this software for any purpose. This software is provided
|
|
9 "as is" without express or implied warranty.
|
|
10
|
|
11 Xtrek Copyright 1986 Chris Guthrie
|
|
12 Netrek (Xtrek II) Copyright 1989 Kevin P. Smith
|
|
13 Scott Silvey
|
|
14 Paradise II (Netrek II) Copyright 1993 Larry Denys
|
|
15 Kurt Olsen
|
|
16 Brandon Gillespie
|
|
17 --------------------------------------------------------------------------*/
|
|
18
|
|
19 #include "config.h"
|
|
20 #include <stdio.h>
|
|
21 #include <math.h>
|
|
22 #include <signal.h>
|
|
23 #include <string.h>
|
|
24
|
|
25 #include "defs.h"
|
|
26 #include "struct.h"
|
|
27 #include "data.h"
|
|
28 #include "daemonII.h"
|
|
29 #include "shmem.h"
|
|
30
|
|
31 #define friendly(fred, bart) \
|
|
32 (!(fred->p_team & (bart->p_swar|bart->p_hostile)) && \
|
|
33 !(bart->p_team & (fred->p_swar|fred->p_hostile)))
|
|
34
|
|
35 /*--------------------------------KILLMESS--------------------------------*/
|
|
36
|
|
37 /*
|
|
38 * This function prints to the messages who killed who. This function now
|
|
39 * adds the way of death onto the end of the kill message.
|
|
40 */
|
|
41
|
|
42
|
|
43 extern void pmessage();
|
|
44 int get_explode_views();
|
|
45 #ifndef SYSV /* this is barfing on HP/UX */
|
|
46 extern int fprintf();
|
|
47 #endif
|
|
48 extern void killerstats();
|
|
49 extern void checkmaxkills();
|
|
50 #ifdef LEAGUE_SUPPORT
|
|
51 extern void tlog_plkill();
|
|
52 #else
|
|
53 #define tlog_plkill(a,b,c)
|
|
54 #endif
|
|
55 extern void loserstats();
|
|
56
|
|
57 void
|
|
58 killmess(victim, killer)
|
|
59 struct player *victim, *killer; /* killee and killer */
|
|
60 {
|
|
61 char buf[80]; /* to sprintf into */
|
|
62
|
|
63 sprintf(buf, "%s (%s", victim->p_name, twoletters(victim));
|
|
64
|
|
65 if (victim->p_armies)
|
|
66 {
|
|
67 if ((victim->p_ship.s_nflags & SFNHASFIGHTERS) && (victim->p_ship.s_type != STARBASE))
|
|
68 sprintf(buf + strlen(buf), "+%d fighters",
|
|
69 victim->p_ship.s_missilestored);
|
|
70 else
|
|
71 sprintf(buf + strlen(buf), "+%d armies", victim->p_armies);
|
|
72 }
|
|
73 strcat(buf, ")");
|
|
74 if (killer)
|
|
75 {
|
|
76 sprintf(buf + strlen(buf), " was kill %0.2f for %s (%s)",
|
|
77 killer->p_kills, killer->p_name,
|
|
78 twoletters(killer));
|
|
79
|
|
80 if (friendly(victim, killer))
|
|
81 strcat(buf, "[no credit]");
|
|
82
|
|
83 }
|
|
84 else
|
|
85 {
|
|
86 if (victim->p_whydead == KPLANET)
|
|
87 {
|
|
88 sprintf(buf + strlen(buf), " was %s by %s (%s)",
|
|
89 PL_TYPE(planets[victim->p_whodead]) == PLSTAR ?
|
|
90 "burned to a crisp" : "shot down",
|
|
91 planets[victim->p_whodead].pl_name,
|
|
92 teams[planets[victim->p_whodead].pl_owner].shortname);
|
|
93 }
|
|
94 else if (victim->p_whydead == KASTEROID)
|
|
95 sprintf(buf + strlen(buf), " was crushed by an asteroid");
|
|
96 else
|
|
97 {
|
|
98 strcat(buf, " was killed");
|
|
99 }
|
|
100 }
|
|
101 switch (victim->p_whydead)
|
|
102 { /* determine why player died */
|
|
103 case KTORP:
|
|
104 strcat(buf, "[torp]");
|
|
105 break;
|
|
106 case KPHASER:
|
|
107 strcat(buf, "[phaser]");
|
|
108 break;
|
|
109 case KSHIP:
|
|
110 strcat(buf, "[explosion]");
|
|
111 break;
|
|
112 case KPLASMA:
|
|
113 strcat(buf, "[plasma]");
|
|
114 break;
|
|
115 case KASTEROID:
|
|
116 strcat(buf, "[asteroid]");
|
|
117 break;
|
|
118 case KPLANET:
|
|
119 switch (PL_TYPE(planets[victim->p_whodead]))
|
|
120 {
|
|
121 case PLSTAR:
|
|
122 strcat(buf, "[star]");
|
|
123 break;
|
|
124 case PLPLANET:
|
|
125 strcat(buf, "[planet]");
|
|
126 break;
|
|
127 default:
|
|
128 strcat(buf, "[space rock]");
|
|
129 break;
|
|
130 }
|
|
131 break;
|
|
132 default:
|
|
133 strcat(buf, "[unknown]");
|
|
134 }
|
|
135 pmessage(buf, 0, MALL | MKILLA, "GOD->ALL");
|
|
136 }
|
|
137
|
|
138
|
|
139
|
|
140
|
|
141 /*-------------------------------VISIBLE FUNCTIONS------------------------*/
|
|
142
|
|
143 /*-------------------------------CAUSE_KABOOM------------------------------*/
|
|
144 /*
|
|
145 * This function sets the victim to explode and sets the counter for the
|
|
146 * explosion views.
|
|
147 */
|
|
148
|
|
149 void
|
|
150 cause_kaboom(victim)
|
|
151 struct player *victim; /* which ship to blast to tiny fragments */
|
|
152 {
|
|
153 victim->p_status = PEXPLODE; /* set player as exploding */
|
|
154 victim->p_explode = (short) get_explode_views(victim->p_ship.s_type);
|
|
155 }
|
|
156
|
|
157 /*------------------------------GET_EXPLODE_VIEWS--------------------------*/
|
|
158 /* returns the number of ship views for the given ship type */
|
|
159
|
|
160 int
|
|
161 get_explode_views(stype)
|
|
162 short stype;
|
|
163 {
|
|
164 switch (stype)
|
|
165 {
|
|
166 case STARBASE:
|
|
167 case WARBASE:
|
|
168 case JUMPSHIP:
|
|
169 return 2 * SBEXPVIEWS / PLAYERFUSE; /* big kablooey */
|
|
170 }
|
|
171 return 10 / PLAYERFUSE; /* small kablooey */
|
|
172 }
|
|
173
|
|
174 /*------------------------------INFLICT_DAMAGE-----------------------------*/
|
|
175 /*
|
|
176 * This function is used to inflict damage on a player. If the player dies
|
|
177 * as a result he will be made to explode. The function returns a 1 if the
|
|
178 * victim was killed and a 0 otherwise. If the sp parameter is a zero then
|
|
179 * the victim was damaged by something other than a ship. It is the
|
|
180 * responsibil- ity of the caller to set the whydead field of the victim.
|
|
181 */
|
|
182
|
|
183 int
|
|
184 inflict_damage(sp, op, victim, damage, why)
|
|
185 struct player *sp; /* player that inflicted the damage */
|
|
186 struct player *op; /* other player that could be responsible */
|
|
187 struct player *victim; /* which ship to victimize */
|
|
188 int damage; /* how much damage, should be positive */
|
|
189 int why; /* the source of the damage */
|
|
190 {
|
|
191 if (damage < 0)
|
|
192 { /* should not be called with - damage */
|
|
193 fprintf(stderr, "Attempt to inflict negative damage\n");
|
|
194 return 0;
|
|
195 }
|
|
196
|
|
197 if (victim->p_flags & PFSHIELD)
|
|
198 { /* shields up? */
|
|
199 int penetrated;
|
|
200 /*
|
|
201 * if the server is configured for damage penetration then the shields
|
|
202 * will not absorb all the damage
|
|
203 */
|
|
204 penetrated = damage * configvals->penetration
|
|
205 * (victim->p_ship.s_maxshield - victim->p_shield)
|
|
206 / (victim->p_ship.s_maxshield);
|
|
207 damage -= penetrated;
|
|
208
|
|
209 victim->p_shield -= damage; /* damage shields */
|
|
210 if (victim->p_shield < 0)
|
|
211 { /* we punched through the shield */
|
|
212 damage = -victim->p_shield; /* excess damage will apply to hull */
|
|
213 victim->p_shield = 0; /* and zero the shields */
|
|
214 }
|
|
215 else
|
|
216 damage = 0;
|
|
217 damage += penetrated; /* some of the damage got through the shields */
|
|
218 }
|
|
219 if (damage > 0)
|
|
220 {
|
|
221 victim->p_damage += damage; /* all damage to hull */
|
|
222 if (configvals->erosion > 0)
|
|
223 {
|
|
224 float chance = damage * configvals->erosion;
|
|
225 while (chance >= 0.5)
|
|
226 { /* no matter how much you suffer there's a
|
|
227 * chance you can avoid permanent damage */
|
|
228 if (lrand48() & 0x40)
|
|
229 {
|
|
230 victim->p_ship.s_maxdamage--; /* apply damage to maximum */
|
|
231 victim->p_damage--; /* instead of current */
|
|
232 }
|
|
233 chance -= 0.5;
|
|
234 }
|
|
235 if (drand48() < chance)
|
|
236 {
|
|
237 victim->p_ship.s_maxdamage--; /* apply damage to maximum */
|
|
238 victim->p_damage--; /* instead of current */
|
|
239 }
|
|
240 }
|
|
241 }
|
|
242
|
|
243 if (victim->p_damage >= victim->p_ship.s_maxdamage)
|
|
244 { /* victim dead? */
|
|
245 cause_kaboom(victim); /* make him explode */
|
|
246 if (sp)
|
|
247 {
|
|
248 victim->p_whydead = why;
|
|
249 if (!friendly(sp, victim)
|
|
250 && sp != victim /* hozers were getting credit for killing
|
|
251 * themselves because they were at war with
|
|
252 their own race */ )
|
|
253 {
|
|
254 /* if a hostile player was responsible */
|
|
255 tlog_plkill(victim, sp, op);
|
|
256 if (victim->p_ship.s_type == PATROL)
|
|
257 sp->p_kills += .5 + ((float) victim->p_armies + victim->p_kills) / 10.0;
|
|
258 else
|
|
259 sp->p_kills += 1.0 + ((float) victim->p_armies + victim->p_kills) / 10.0;
|
|
260 killerstats(sp->p_no, victim); /* adjust everyones stats */
|
|
261 checkmaxkills(sp->p_no);
|
|
262 killmess(victim, sp);
|
|
263 victim->p_whodead = sp->p_no;
|
|
264 }
|
|
265 else if (op && !friendly(op, victim) && op != victim)
|
|
266 {
|
|
267 /* the primary assassin was friendly, check auxiliary killer */
|
|
268 tlog_plkill(victim, op, sp);
|
|
269
|
|
270 if (victim->p_ship.s_type == PATROL)
|
|
271 op->p_kills += .5 + ((float) victim->p_armies + victim->p_kills) / 10.0;
|
|
272 else
|
|
273 op->p_kills += 1.0 + ((float) victim->p_armies + victim->p_kills) / 10.0;
|
|
274 killerstats(op->p_no, victim); /* adjust everyones stats */
|
|
275 checkmaxkills(op->p_no);
|
|
276 killmess(victim, op);
|
|
277 victim->p_whodead = op->p_no;
|
|
278 }
|
|
279 else
|
|
280 {
|
|
281 /*
|
|
282 * give no credit since it was friendly and the auxiliary murderer
|
|
283 * was friendly too
|
|
284 */
|
|
285 tlog_plkill(victim, sp, (struct player *) 0);
|
|
286 killmess(victim, sp);
|
|
287 victim->p_whodead = sp->p_no;
|
|
288 }
|
|
289 }
|
|
290 loserstats(victim->p_no);
|
|
291 return 1; /* victim died */
|
|
292 }
|
|
293 else
|
|
294 return 0; /* victim lived */
|
|
295 }
|
|
296
|
|
297 /*-------------------------------------------------------------------------*/
|
|
298
|
|
299
|
|
300 struct ranksorter
|
|
301 {
|
|
302 int pno;
|
|
303 int rank;
|
|
304 float di;
|
|
305 int teammates;
|
|
306 };
|
|
307
|
|
308 static struct ranksorter admirals[MAXTEAM];
|
|
309
|
|
310 int
|
|
311 enemy_admiral(tno)
|
|
312 int tno;
|
|
313 {
|
|
314 int teammates;
|
|
315 int pno;
|
|
316 int i;
|
|
317
|
|
318 for (i = 0; i < MAXTEAM; i++)
|
|
319 {
|
|
320 admirals[i].teammates = 0;
|
|
321 admirals[i].rank = -1;
|
|
322 }
|
|
323
|
|
324 for (i = 0; i < MAXPLAYER; i++)
|
|
325 {
|
|
326 int team;
|
|
327 struct player *pl;
|
|
328 pl = &players[i];
|
|
329
|
|
330 if (pl->p_status == PFREE ||
|
|
331 pl->p_team == tno)
|
|
332 continue;
|
|
333
|
|
334 team = pl->p_team;
|
|
335 admirals[team].teammates++;
|
|
336
|
|
337 if (pl->p_stats.st_rank < admirals[team].rank)
|
|
338 continue;
|
|
339 if (pl->p_stats.st_rank > admirals[team].rank ||
|
|
340 pl->p_stats.st_di > admirals[team].di)
|
|
341 {
|
|
342 admirals[team].pno = i;
|
|
343 admirals[team].rank = pl->p_stats.st_rank;
|
|
344 admirals[team].di = pl->p_stats.st_di;
|
|
345 }
|
|
346 }
|
|
347
|
|
348 teammates = -1;
|
|
349 pno = 0;
|
|
350 for (i = 0; i < MAXTEAM; i++)
|
|
351 {
|
|
352 if (admirals[i].teammates > teammates)
|
|
353 {
|
|
354 pno = admirals[i].pno;
|
|
355 teammates = admirals[i].teammates;
|
|
356 }
|
|
357 }
|
|
358 return pno;
|
|
359 }
|
|
360
|
|
361
|
|
362 /*--------END OF FILE-------*/
|