comparison src/dutil.c @ 3:cafa94d86546

Initial revision
author darius
date Sat, 06 Dec 1997 04:37:01 +0000
parents
children d28f3d01043c
comparison
equal deleted inserted replaced
2:2719a89505ba 3:cafa94d86546
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-------*/