Mercurial > ~darius > hgwebdir.cgi > paradise_server
diff src/dutil.c @ 3:cafa94d86546
Initial revision
author | darius |
---|---|
date | Sat, 06 Dec 1997 04:37:01 +0000 |
parents | |
children | d28f3d01043c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dutil.c Sat Dec 06 04:37:01 1997 +0000 @@ -0,0 +1,362 @@ +/*-------------------------------------------------------------------------- +NETREK II -- Paradise + +Permission to use, copy, modify, and distribute this software and its +documentation, or any derivative works thereof, for any NON-COMMERCIAL +purpose and without fee is hereby granted, provided that this copyright +notice appear in all copies. No representations are made about the +suitability of this software for any purpose. This software is provided +"as is" without express or implied warranty. + + Xtrek Copyright 1986 Chris Guthrie + Netrek (Xtrek II) Copyright 1989 Kevin P. Smith + Scott Silvey + Paradise II (Netrek II) Copyright 1993 Larry Denys + Kurt Olsen + Brandon Gillespie +--------------------------------------------------------------------------*/ + +#include "config.h" +#include <stdio.h> +#include <math.h> +#include <signal.h> +#include <string.h> + +#include "defs.h" +#include "struct.h" +#include "data.h" +#include "daemonII.h" +#include "shmem.h" + +#define friendly(fred, bart) \ + (!(fred->p_team & (bart->p_swar|bart->p_hostile)) && \ + !(bart->p_team & (fred->p_swar|fred->p_hostile))) + +/*--------------------------------KILLMESS--------------------------------*/ + +/* + * This function prints to the messages who killed who. This function now + * adds the way of death onto the end of the kill message. + */ + + +extern void pmessage(); +int get_explode_views(); +#ifndef SYSV /* this is barfing on HP/UX */ +extern int fprintf(); +#endif +extern void killerstats(); +extern void checkmaxkills(); +#ifdef LEAGUE_SUPPORT +extern void tlog_plkill(); +#else +#define tlog_plkill(a,b,c) +#endif +extern void loserstats(); + +void +killmess(victim, killer) + struct player *victim, *killer; /* killee and killer */ +{ + char buf[80]; /* to sprintf into */ + + sprintf(buf, "%s (%s", victim->p_name, twoletters(victim)); + + if (victim->p_armies) + { + if ((victim->p_ship.s_nflags & SFNHASFIGHTERS) && (victim->p_ship.s_type != STARBASE)) + sprintf(buf + strlen(buf), "+%d fighters", + victim->p_ship.s_missilestored); + else + sprintf(buf + strlen(buf), "+%d armies", victim->p_armies); + } + strcat(buf, ")"); + if (killer) + { + sprintf(buf + strlen(buf), " was kill %0.2f for %s (%s)", + killer->p_kills, killer->p_name, + twoletters(killer)); + + if (friendly(victim, killer)) + strcat(buf, "[no credit]"); + + } + else + { + if (victim->p_whydead == KPLANET) + { + sprintf(buf + strlen(buf), " was %s by %s (%s)", + PL_TYPE(planets[victim->p_whodead]) == PLSTAR ? + "burned to a crisp" : "shot down", + planets[victim->p_whodead].pl_name, + teams[planets[victim->p_whodead].pl_owner].shortname); + } + else if (victim->p_whydead == KASTEROID) + sprintf(buf + strlen(buf), " was crushed by an asteroid"); + else + { + strcat(buf, " was killed"); + } + } + switch (victim->p_whydead) + { /* determine why player died */ + case KTORP: + strcat(buf, "[torp]"); + break; + case KPHASER: + strcat(buf, "[phaser]"); + break; + case KSHIP: + strcat(buf, "[explosion]"); + break; + case KPLASMA: + strcat(buf, "[plasma]"); + break; + case KASTEROID: + strcat(buf, "[asteroid]"); + break; + case KPLANET: + switch (PL_TYPE(planets[victim->p_whodead])) + { + case PLSTAR: + strcat(buf, "[star]"); + break; + case PLPLANET: + strcat(buf, "[planet]"); + break; + default: + strcat(buf, "[space rock]"); + break; + } + break; + default: + strcat(buf, "[unknown]"); + } + pmessage(buf, 0, MALL | MKILLA, "GOD->ALL"); +} + + + + +/*-------------------------------VISIBLE FUNCTIONS------------------------*/ + +/*-------------------------------CAUSE_KABOOM------------------------------*/ +/* + * This function sets the victim to explode and sets the counter for the + * explosion views. + */ + +void +cause_kaboom(victim) + struct player *victim; /* which ship to blast to tiny fragments */ +{ + victim->p_status = PEXPLODE; /* set player as exploding */ + victim->p_explode = (short) get_explode_views(victim->p_ship.s_type); +} + +/*------------------------------GET_EXPLODE_VIEWS--------------------------*/ +/* returns the number of ship views for the given ship type */ + +int +get_explode_views(stype) + short stype; +{ + switch (stype) + { + case STARBASE: + case WARBASE: + case JUMPSHIP: + return 2 * SBEXPVIEWS / PLAYERFUSE; /* big kablooey */ + } + return 10 / PLAYERFUSE; /* small kablooey */ +} + +/*------------------------------INFLICT_DAMAGE-----------------------------*/ +/* + * This function is used to inflict damage on a player. If the player dies + * as a result he will be made to explode. The function returns a 1 if the + * victim was killed and a 0 otherwise. If the sp parameter is a zero then + * the victim was damaged by something other than a ship. It is the + * responsibil- ity of the caller to set the whydead field of the victim. + */ + +int +inflict_damage(sp, op, victim, damage, why) + struct player *sp; /* player that inflicted the damage */ + struct player *op; /* other player that could be responsible */ + struct player *victim; /* which ship to victimize */ + int damage; /* how much damage, should be positive */ + int why; /* the source of the damage */ +{ + if (damage < 0) + { /* should not be called with - damage */ + fprintf(stderr, "Attempt to inflict negative damage\n"); + return 0; + } + + if (victim->p_flags & PFSHIELD) + { /* shields up? */ + int penetrated; + /* + * if the server is configured for damage penetration then the shields + * will not absorb all the damage + */ + penetrated = damage * configvals->penetration + * (victim->p_ship.s_maxshield - victim->p_shield) + / (victim->p_ship.s_maxshield); + damage -= penetrated; + + victim->p_shield -= damage; /* damage shields */ + if (victim->p_shield < 0) + { /* we punched through the shield */ + damage = -victim->p_shield; /* excess damage will apply to hull */ + victim->p_shield = 0; /* and zero the shields */ + } + else + damage = 0; + damage += penetrated; /* some of the damage got through the shields */ + } + if (damage > 0) + { + victim->p_damage += damage; /* all damage to hull */ + if (configvals->erosion > 0) + { + float chance = damage * configvals->erosion; + while (chance >= 0.5) + { /* no matter how much you suffer there's a + * chance you can avoid permanent damage */ + if (lrand48() & 0x40) + { + victim->p_ship.s_maxdamage--; /* apply damage to maximum */ + victim->p_damage--; /* instead of current */ + } + chance -= 0.5; + } + if (drand48() < chance) + { + victim->p_ship.s_maxdamage--; /* apply damage to maximum */ + victim->p_damage--; /* instead of current */ + } + } + } + + if (victim->p_damage >= victim->p_ship.s_maxdamage) + { /* victim dead? */ + cause_kaboom(victim); /* make him explode */ + if (sp) + { + victim->p_whydead = why; + if (!friendly(sp, victim) + && sp != victim /* hozers were getting credit for killing + * themselves because they were at war with + their own race */ ) + { + /* if a hostile player was responsible */ + tlog_plkill(victim, sp, op); + if (victim->p_ship.s_type == PATROL) + sp->p_kills += .5 + ((float) victim->p_armies + victim->p_kills) / 10.0; + else + sp->p_kills += 1.0 + ((float) victim->p_armies + victim->p_kills) / 10.0; + killerstats(sp->p_no, victim); /* adjust everyones stats */ + checkmaxkills(sp->p_no); + killmess(victim, sp); + victim->p_whodead = sp->p_no; + } + else if (op && !friendly(op, victim) && op != victim) + { + /* the primary assassin was friendly, check auxiliary killer */ + tlog_plkill(victim, op, sp); + + if (victim->p_ship.s_type == PATROL) + op->p_kills += .5 + ((float) victim->p_armies + victim->p_kills) / 10.0; + else + op->p_kills += 1.0 + ((float) victim->p_armies + victim->p_kills) / 10.0; + killerstats(op->p_no, victim); /* adjust everyones stats */ + checkmaxkills(op->p_no); + killmess(victim, op); + victim->p_whodead = op->p_no; + } + else + { + /* + * give no credit since it was friendly and the auxiliary murderer + * was friendly too + */ + tlog_plkill(victim, sp, (struct player *) 0); + killmess(victim, sp); + victim->p_whodead = sp->p_no; + } + } + loserstats(victim->p_no); + return 1; /* victim died */ + } + else + return 0; /* victim lived */ +} + +/*-------------------------------------------------------------------------*/ + + +struct ranksorter +{ + int pno; + int rank; + float di; + int teammates; +}; + +static struct ranksorter admirals[MAXTEAM]; + +int +enemy_admiral(tno) + int tno; +{ + int teammates; + int pno; + int i; + + for (i = 0; i < MAXTEAM; i++) + { + admirals[i].teammates = 0; + admirals[i].rank = -1; + } + + for (i = 0; i < MAXPLAYER; i++) + { + int team; + struct player *pl; + pl = &players[i]; + + if (pl->p_status == PFREE || + pl->p_team == tno) + continue; + + team = pl->p_team; + admirals[team].teammates++; + + if (pl->p_stats.st_rank < admirals[team].rank) + continue; + if (pl->p_stats.st_rank > admirals[team].rank || + pl->p_stats.st_di > admirals[team].di) + { + admirals[team].pno = i; + admirals[team].rank = pl->p_stats.st_rank; + admirals[team].di = pl->p_stats.st_di; + } + } + + teammates = -1; + pno = 0; + for (i = 0; i < MAXTEAM; i++) + { + if (admirals[i].teammates > teammates) + { + pno = admirals[i].pno; + teammates = admirals[i].teammates; + } + } + return pno; +} + + +/*--------END OF FILE-------*/